-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Implement NativeCallableMethods for CoreCLR #1566
Conversation
Hi @tijoytom, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution! TTYL, DNFBOT; |
@tijoytom, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR. |
@@ -153,6 +157,21 @@ LOCAL_LABEL(DoThreadSetup): | |||
call C_FUNC(CreateThreadBlockThrow) | |||
jmp LOCAL_LABEL(HaveThread) | |||
|
|||
LOCAL_LABEL(InvalidTransition): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct for Unix. There is no homing of argument registers and the argument registers are different from Windows. See the stack layout starting at line 44 in this file.
@tijoytom, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR. |
@dotnet-bot test this please |
@@ -279,6 +283,21 @@ DoThreadSetup: | |||
|
|||
jmp HaveThread | |||
|
|||
InvalidTransition: | |||
mov [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 0h], rcx | |||
mov [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 8h], rdx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please remove this setup as well - to match what you have done for Unix?
LGTM. Could you please squash everything into a single commit before merging? |
Apply [NativeCallable] attribute to a managed method and then it can be called from native code.Typical use would be passing a managed method as callback to native, now it can be done by wrapping the method in a delegate or directly using Marshal.GetFunctionPointerForDelegate.This's fine as long as we make sure that delegate is not garbage collected.[NativeCallable] introduce another way, where you can directly load the function pointer of a native callable method and use it as callback.This feature cannot be directly used from C#,but can be very useful in dynamic code generation scenarios where you want a callback to be passed to native. Here's an example of how it can be used. public static class NativeMethods { [DllImport("user32.dll")] public static extern int EnumWindows(IntPtr enumProc, IntPtr lParam); } //Method attributed with NativeCallable [NativeCallable] public static int CallbackMethod(IntPtr hWnd, IntPtr lParam){ return 1; } Now you can generate the below IL to load native callable function pointer ( LDFTN) and then pass it a native method. .locals init ([0] native int ptr) nop ldftn int32 CallbackMethod(native int,native int) stloc.0 ldloc.0 ldsfld native int System.IntPtr::Zero call bool NativeMethods::EnumWindows(native int,native int) pop ret Encoding native callable methods as ENCODE_METHOD_NATIVECALLABLE_HANDLE so that we don't have to check for the custom attribute at runtime to decode the method.Also fixing the remaining code review comments. Adding runtime check to prevent Native Callable methods from being used as calli target with an ldftn. Also adding some negative test cases , they are disabled for now since the tests failfast and msbuild report it as failure.
This's the test failing on FreeBSD , not sure if it has anything to with this change. |
Ignore the PAL failure. The PAL tests are known to fail once in a while because of the virtual machine that they are running on happen to be slow. We have fixed the worst offenders by raising the tolerances but there are still some left ... |
@dotnet-bot test this please |
Implement NativeCallableMethods for CoreCLR
Implement NativeCallableMethods for CoreCLR Commit migrated from dotnet/coreclr@9fa52c4
Feature Description
Apply [NativeCallable] attribute to a managed method and then it can be called from native code.Typical use would be passing a managed method as callback to native , now it can be done by wrapping the method in a delegate or directly using Marshal.GetFunctionPointerForDelegate.This's fine as long as we make sure that delegate is not garbage collected.
[NativeCallable] introduce another way , where you can directly load the function pointer of a native callable method and use it as callback.This feature cannot be directly used from C# , but can be very useful in dynamic code generation scenarios where you want a callback to be passed to native.
Usage
Here's an example of how it can be used.
public static class NativeMethods
{
[DllImport("user32.dll")]
public static extern int EnumWindows(IntPtr enumProc, IntPtr lParam);
}
// Native callable callback method
[NativeCallable]
public static int CallbackMethod(IntPtr hWnd, IntPtr lParam)
{
return 1;
}
Now you can generate the below IL to load native callable function pointer ( LDFTN) and then pass it a native method.
Implementation
During JIT we treat method with [NativeCallable] attribute as special and create a reverse PInvoke thunk for it. Essentially it takes the same code path as reverse pinvoke.
Advantages and Limitations
Advantages of this method are , you don't have to create delegate matching the callback , and also you don't have to keep track of the delegates to make sure they are not collected.
Currently we require the native callable method to be
1.Static , Non Generic and no variable number of arguments.
2.Uses only blittable parameter types.