-#Mscorlib and Calling Into the Runtime
+Mscorlib and Calling Into the Runtime
+===
Author: Brian Grunkemeyer (@briangru) - 2006
# Introduction
class Foo
{
- // All QCalls should have the following DllImport and
- // SuppressUnmanagedCodeSecurity attributes
- [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
- [SuppressUnmanagedCodeSecurity]
- // QCalls should always be static extern.
- private static extern bool Bar(int flags, string inString, StringHandleOnStack retString);
-
- // Many QCalls have a thin managed wrapper around them to expose them to
- // the world in more meaningful way.
- public string Bar(int flags)
- {
- string retString = null;
-
- // The strings are returned from QCalls by taking address
- // of a local variable using JitHelpers.GetStringHandle method
- if (!Bar(flags, this.Id, JitHelpers.GetStringHandle(ref retString)))
- FatalError();
-
+ // All QCalls should have the following DllImport and
+ // SuppressUnmanagedCodeSecurity attributes
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ // QCalls should always be static extern.
+ private static extern bool Bar(int flags, string inString, StringHandleOnStack retString);
+
+ // Many QCalls have a thin managed wrapper around them to expose them to
+ // the world in more meaningful way.
+ public string Bar(int flags)
+ {
+ string retString = null;
+
+ // The strings are returned from QCalls by taking address
+ // of a local variable using JitHelpers.GetStringHandle method
+ if (!Bar(flags, this.Id, JitHelpers.GetStringHandle(ref retString)))
+ FatalError();
+
return retString;
- }
+ }
}
### QCall Example - Unmanaged Part
[ecalllist]: https://github.com/dotnet/coreclr/blob/master/src/vm/ecalllist.h
-class FooNative
+ class FooNative
{
public:
// All QCalls should be static and should be tagged with QCALLTYPE
BOOL QCALLTYPE FooNative::Bar(int flags, LPCWSTR wszString, QCall::StringHandleOnStack retString)
{
- // All QCalls should have QCALL_CONTRACT.
- // It is alias for THROWS; GC_TRIGGERS; MODE_PREEMPTIVE; SO_TOLERANT.
- QCALL_CONTRACT;
-
- // Optionally, use QCALL_CHECK instead and the expanded form of the contract
- // if you want to specify preconditions:
- // CONTRACTL {
- // QCALL_CHECK;
- // PRECONDITION(wszString != NULL);
- // } CONTRACTL_END;
-
- // The only line between QCALL_CONTRACT and BEGIN_QCALL
- // should be the return value declaration if there is one.
- BOOL retVal = FALSE;
-
- // The body has to be enclosed in BEGIN_QCALL/END_QCALL macro. It is necessary
- // to make the exception handling work.
- BEGIN_QCALL;
-
- // Validate arguments if necessary and throw exceptions.
- // There is no convention currently on whether the argument validation should be
- // done in managed or unmanaged code.
- if (flags != 0)
- COMPlusThrow(kArgumentException, L"InvalidFlags");
-
- // No need to worry about GC moving strings passed into QCall.
- // Marshalling pins them for us.
- printf("%S", wszString);
-
- // This is most the efficient way to return strings back
- // to managed code. No need to use StringBuilder.
- retString.Set(L"Hello");
-
- // You can not return from inside of BEGIN_QCALL/END_QCALL.
- // The return value has to be passed out in helper variable.
- retVal = TRUE;
-
- END_QCALL;
-
- return retVal;
- }
+ // All QCalls should have QCALL_CONTRACT.
+ // It is alias for THROWS; GC_TRIGGERS; MODE_PREEMPTIVE; SO_TOLERANT.
+ QCALL_CONTRACT;
+
+ // Optionally, use QCALL_CHECK instead and the expanded form of the contract
+ // if you want to specify preconditions:
+ // CONTRACTL {
+ // QCALL_CHECK;
+ // PRECONDITION(wszString != NULL);
+ // } CONTRACTL_END;
+
+ // The only line between QCALL_CONTRACT and BEGIN_QCALL
+ // should be the return value declaration if there is one.
+ BOOL retVal = FALSE;
+
+ // The body has to be enclosed in BEGIN_QCALL/END_QCALL macro. It is necessary
+ // to make the exception handling work.
+ BEGIN_QCALL;
+
+ // Validate arguments if necessary and throw exceptions.
+ // There is no convention currently on whether the argument validation should be
+ // done in managed or unmanaged code.
+ if (flags != 0)
+ COMPlusThrow(kArgumentException, L"InvalidFlags");
+
+ // No need to worry about GC moving strings passed into QCall.
+ // Marshalling pins them for us.
+ printf("%S", wszString);
+
+ // This is most the efficient way to return strings back
+ // to managed code. No need to use StringBuilder.
+ retString.Set(L"Hello");
+
+ // You can not return from inside of BEGIN_QCALL/END_QCALL.
+ // The return value has to be passed out in helper variable.
+ retVal = TRUE;
+
+ END_QCALL;
+
+ return retVal;
+ }
## FCall Functional Behavior