// // trampoline must be static, and someone else needs to keep a ref to it // public unsafe void SetupBlock(Delegate trampoline, Delegate userDelegate) { isa = block_class; invoke = Marshal.GetFunctionPointerForDelegate(trampoline); local_handle = (IntPtr)GCHandle.Alloc(userDelegate); global_handle = IntPtr.Zero; flags = BlockFlags.BLOCK_HAS_COPY_DISPOSE | BlockFlags.BLOCK_HAS_SIGNATURE; /* FIXME: support stret blocks */ // we allocate one big block of memory, the first part is the BlockDescriptor, // the second part is the signature string (no need to allocate a second time // for the signature if we can avoid it). One descriptor is allocated for every // Block; this is potentially something the static registrar can fix, since it // should know every possible trampoline signature. var signature = Runtime.ComputeSignature(trampoline.Method); var bytes = System.Text.Encoding.UTF8.GetBytes(signature); var desclen = sizeof(XamarinBlockDescriptor) + bytes.Length + 1 /* null character */; var descptr = Marshal.AllocHGlobal(desclen); block_descriptor = descptr; var xblock_descriptor = (XamarinBlockDescriptor *)block_descriptor; xblock_descriptor->descriptor = *(BlockDescriptor *)xamarin_get_block_descriptor(); xblock_descriptor->descriptor.signature = descptr + sizeof(BlockDescriptor) + 4 /* signature_length */; xblock_descriptor->xamarin_size = desclen; Marshal.Copy(bytes, 0, xblock_descriptor->descriptor.signature, bytes.Length); Marshal.WriteByte(xblock_descriptor->descriptor.signature + bytes.Length, 0); // null terminate string }
// // trampoline must be static, and someone else needs to keep a ref to it // public unsafe void SetupBlock(Delegate trampoline, Delegate userDelegate) { isa = block_class; invoke = Marshal.GetFunctionPointerForDelegate(trampoline); local_handle = (IntPtr)GCHandle.Alloc(userDelegate); global_handle = IntPtr.Zero; flags = BlockFlags.BLOCK_HAS_COPY_DISPOSE | BlockFlags.BLOCK_HAS_SIGNATURE; /* FIXME: support stret blocks */ // We need to get the signature of the target method, so that we can compute // the ObjC signature correctly (the generated method that's actually // invoked by native code does not have enough type information to compute // the correct signature). // This attribute might not exist for third-party libraries created // with earlier versions of Xamarin.iOS, so make sure to cope with // the attribute not being available. var userDelegateType = trampoline.GetType().GetCustomAttribute <UserDelegateTypeAttribute> ()?.UserDelegateType; bool blockSignature; MethodInfo userMethod; if (userDelegateType != null) { userMethod = userDelegateType.GetMethod("Invoke"); blockSignature = true; } else { userMethod = trampoline.Method; blockSignature = false; } // we allocate one big block of memory, the first part is the BlockDescriptor, // the second part is the signature string (no need to allocate a second time // for the signature if we can avoid it). One descriptor is allocated for every // Block; this is potentially something the static registrar can fix, since it // should know every possible trampoline signature. var signature = Runtime.ComputeSignature(userMethod, blockSignature); var bytes = System.Text.Encoding.UTF8.GetBytes(signature); var desclen = sizeof(XamarinBlockDescriptor) + bytes.Length + 1 /* null character */; var descptr = Marshal.AllocHGlobal(desclen); block_descriptor = descptr; var xblock_descriptor = (XamarinBlockDescriptor *)block_descriptor; xblock_descriptor->descriptor = *(BlockDescriptor *)xamarin_get_block_descriptor(); xblock_descriptor->descriptor.signature = descptr + sizeof(BlockDescriptor) + 4 /* signature_length */; xblock_descriptor->ref_count = 1; Marshal.Copy(bytes, 0, xblock_descriptor->descriptor.signature, bytes.Length); Marshal.WriteByte(xblock_descriptor->descriptor.signature + bytes.Length, 0); // null terminate string }