-
Notifications
You must be signed in to change notification settings - Fork 514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Redesign Block support to make it work with UnmanagedCallersOnlyAttribute #15783
Comments
Tentative implementation: rolfbjarne@3139dfb This is the important part: unsafe {
var trampoline = (delegate* unmanaged<IntPtr, IntPtr, byte, byte>) &TrampolineRegistrationHandlerCallback;
using var block = new BlockLiteral (trampoline, registrationHandler, typeof (CTFontManager), nameof (TrampolineRegistrationHandlerCallback));
CTFontManagerRegisterFontURLs (arr.Handle, scope, enabled, &block);
} it's a bit more verbose than I wished, but I don't think there's a way around that:
|
If dotnet/designs#282 is ever approved and implemented, a minor improvement might be something like this: unsafe {
var trampoline = (delegate* unmanaged<IntPtr, IntPtr, byte, byte>) &TrampolineRegistrationHandlerCallback;
var trampolineType = typeof (delegate* unmanaged<IntPtr, IntPtr, byte, byte>);
using var block = new BlockLiteral (trampoline, registrationHandler, trampolineType);
CTFontManagerRegisterFontURLs (arr.Handle, scope, enabled, &block);
} |
How gross are we allowed to get in the code? Like, can we assume that a C# delegate is just a struct with two machine pointers in it and pass that through along with the delegate type then on the receiving end of the trampoline hard cast it back and invoke it? I feel like I did something like this in BTfS. |
Ideally the code would be nice, because it'll be how users use blocks (which isn't very common, but once in a while it happens). Also, we can't use a delegate to pass the signature, because you can't create a delegate of a method with an [UnmanagedCallersOnly] attribute. |
from the options to step 1 I think I lean more for delegate* unmanaged<IntPtr, IntPtr, byte, byte> trampoline = &TrampolineRegistrationHandlerCallback; less parenthesis heh, it feels just slightly more readable to me but just slightly 😃 the rest 👍 |
It seems we'll be able to do something like this in the future: using Signature = delegate* unmanaged<IntPtr, IntPtr, byte, byte>;
unsafe {
Signature trampoline = &TrampolineRegistrationHandlerCallback;
using var block = new BlockLiteral (trampoline, registrationHandler, typeof (CTFontManager), nameof (TrampolineRegistrationHandlerCallback));
CTFontManagerRegisterFontURLs (arr.Handle, scope, enabled, &block);
} which, together with the function pointer type change, could become: using Signature = delegate* unmanaged<IntPtr, IntPtr, byte, byte>;
unsafe {
using var block = new BlockLiteral ((Signature) &trampoline, registrationHandler, typeof (Signature));
CTFontManagerRegisterFontURLs (arr.Handle, scope, enabled, &block);
} |
) * Make BlockLiteral disposable. This also means to modify the cleanup logic so that it's safe to call Dispose more than once. * Create a helper class to create a block for a simple Action delegate. This allows us to simplify a good chunk of code. * Update all block creation to use the new block API, where blocks are disposable. This makes the code pattern a lot simpler. I've changed all the P/Invokes to use an unsafe 'BlockLiteral*' pointer, because 'using' variables can't be passed as ref arguments, so the choice was either to make the parameter type 'IntPtr' and cast away the pointer: using var block = new BlockLiteral (); PInvoke ((IntPtr) &block); or make the parameter an unsafe 'BlockLiteral*' pointer: unsafe { using var block = new BlockLiteral (); PInvoke (&block); } The upcoming support for function pointers don't have this choice: function pointers are always unsafe, so I chose to go the unsafe route here as well, since it makes the code simpler once support for function pointers has been implemented. Contributes towards #15783. This PR might be easier to review commit-by-commit.
Contributes towards xamarin#15783.
This is mostly converting 'bool' arguments to 'byte' arguments, and 'string' arguments to 'IntPtr' with custom utf8->string conversions. This is necessary in order to convert all block callbacks to use UnmanagedCallersOnly function pointers (which can't have non-blittable types in their signature). Contributes towards xamarin#15783.
This is mostly converting 'bool' arguments to 'byte' arguments, and 'string' arguments to 'IntPtr' with custom utf8->string conversions. This is necessary in order to convert all block callbacks to use UnmanagedCallersOnly function pointers (which can't have non-blittable types in their signature). Contributes towards #15783.
This is necessary in order to convert all block callbacks to use UnmanagedCallersOnly function pointers (which can't have non-blittable types in their signature). Contributes towards xamarin#15783.
This is necessary in order to convert all block callbacks to use UnmanagedCallersOnly function pointers (which can't have non-blittable types in their signature). Contributes towards xamarin#15783.
This is necessary in order to convert all block callbacks to use UnmanagedCallersOnly function pointers (which can't have non-blittable types in their signature). Contributes towards #15783.
Add support for function pointers to BlockLiteral, and use it to update almost all manually bound block code to use function pointers (in .NET). Also add support to the linker for optimizing the new block API. Contributes towards #15783.
…ypes. Change the generated block callbacks so that we only use blittable types (so that the callbacks can become [UnmanagedCallersOnly]). This involved two changes: * Use pointer types instead of ref/out types ('int*' instead of 'ref/out int'). * Use 'byte' instead of 'bool'. Contributes towards xamarin#15783.
…ypes. Change the generated block callbacks so that we only use blittable types (so that the callbacks can become [UnmanagedCallersOnly]). This involved two changes: * Use pointer types instead of ref/out types ('int*' instead of 'ref/out int'). * Use 'byte' instead of 'bool'. Contributes towards xamarin#15783.
…ypes. Change the generated block callbacks so that we only use blittable types (so that the callbacks can become [UnmanagedCallersOnly]). This involved two changes: * Use pointer types instead of ref/out types ('int*' instead of 'ref/out int'). * Use 'byte' instead of 'bool'. Contributes towards xamarin#15783.
…ypes. (#17712) Change the generated block callbacks so that we only use blittable types (so that the callbacks can become [UnmanagedCallersOnly]). This involved two changes: * Use pointer types instead of ref/out types ('int*' instead of 'ref/out int'). * Use 'byte' instead of 'bool'. Contributes towards #15783.
…n .NET. Contributes towards xamarin#15783.
…our own code. Fixes xamarin#15783. This is the final step in our improved block support. Fixes xamarin#15783.
…our own code. Fixes #15783. (#17794) This is the final step in our improved block support. Fixes #15783. Co-authored-by: Manuel de la Pena <[email protected]>
Ref: #10470 (comment)
Ideally any changes would also cover (which I've closed as duplicates of this issue):
The text was updated successfully, but these errors were encountered: