Beispiel #1
0
        //
        // 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
        }
Beispiel #2
0
        //
        // 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
        }