Exemple #1
0
        /// <summary>
        /// Returns a native function pointer to a stub method that sets the value
        /// of the given static or instance field.
        /// </summary>
        /// <remarks>
        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
        /// </remarks>
        public static IntPtr GenerateFieldSetStub(FieldInfo field)
        {
            // Signature of the stub method returned (as a delegate) by this function
            DelegateSignature methodSignature = new DelegateSignature(
                typeof(void),
                field.IsStatic ?
                new Type[] { ConvertToStubType(field.FieldType) } :
                new Type[] { ConvertToStubType(field.DeclaringType), ConvertToStubType(field.FieldType) });

            return(GenerateDynamicMethod(field.DeclaringType.Name + "_field_set_" + field.Name, methodSignature,
                                         delegate(ILGenerator ilg)
            {
                if (field.IsStatic)
                {
                    // Load (and unmarshal) the field value from the stub call
                    EmitParameterLoading(ilg, 0, field.FieldType);
                    ilg.Emit(OpCodes.Stsfld, field);
                }
                else
                {
                    // Load (and unmarshal) the instance argument and field value from the stub call
                    EmitParameterLoading(ilg, 0, field.DeclaringType);
                    EmitParameterLoading(ilg, 1, field.FieldType);
                    ilg.Emit(OpCodes.Stfld, field);
                }

                ilg.Emit(OpCodes.Ret);
            }));
        }
Exemple #2
0
        /// <summary>
        /// Returns a native function pointer to a wrapper stub that accepts foreign
        /// parameters, marshals them, calls the indicated constructor, and returns the
        /// resulting object instance (marshaled as necessary).
        /// </summary>
        /// <remarks>
        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
        /// When used to construct a value type, 'con' may be null, in which case
        /// no constructor is called (the value is just initialised to zero).
        /// </remarks>
        public static IntPtr GenerateConstructorStub(ConstructorInfo con)
        {
            Type type = con.DeclaringType;

            if (!type.IsValueType && con == null)
            {
                throw new ArgumentNullException("'con' cannot be null if creating a reference type.");
            }

            // Generate a dynamic method that does the following:
            //
            //     Int32 [classType]New([args...])
            //     {
            //         [classType] o = new [classType]([args... using GetObject ... ]);
            //         (box o if it is a value type)
            //         return Driver.RegisterObject(o);
            //     }

            // Signature of the stub method returned (as a delegate) by this function
            DelegateSignature methodSignature = new DelegateSignature(
                typeof(Int32),
                con == null ? Type.EmptyTypes :
                ConvertToStubTypes(Util.MapParametersToTypes(con.GetParameters())));

            return(GenerateDynamicMethod(type.Name + "New", methodSignature,
                                         delegate(ILGenerator ilg)
            {
                if (con == null)     // Initialise object to zero?
                {
                    // Initialise the object in a local variable
                    ilg.DeclareLocal(type);
                    ilg.Emit(OpCodes.Ldloca_S, (byte)0);
                    ilg.Emit(OpCodes.Initobj, type);

                    // Load the object onto the stack
                    ilg.Emit(OpCodes.Ldloc_0);
                }
                else     // Call object constructor:
                {
                    // Load (and unmarshal), the arguments to the constructor stub
                    EmitParameterLoading(ilg, 0, con.GetParameters());

                    // Call the constructor, i.e. 'o = new [classType]([unmarshaled args])'
                    ilg.Emit(OpCodes.Newobj, con);
                }

                // Return the new object (marshaled as an index)
                EmitToStub(ilg, type);
                ilg.Emit(OpCodes.Ret);
            }));
        }
Exemple #3
0
        /// <summary>
        /// Returns a native function pointer to a stub method that calls the given
        /// method, marshaling arguments as necessary.
        /// </summary>
        /// <remarks>
        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
        /// </remarks>
        public static IntPtr GenerateMethodStub(MethodInfo meth)
        {
            Type classType = meth.DeclaringType;

            // Generate a dynamic method that does the following:
            //
            //     [stubReturnType] [classType]_[methodName]([classType] this, [args...])
            //       OR (if a static method)
            //     [stubReturnType] [classType]_[methodName]([args...])
            //     {
            //         [resultType] r = this.[methodName]([marshaledThis], [marshaled args]);
            //           OR (if a static method)
            //         [resultType] r = [className].[methodName]([marshaled args]);
            //
            //         return r; OR return Driver.RegisterObject(r);
            //     }

            // Signature of the stub method returned (as a delegate) by this function
            DelegateSignature methodSignature = new DelegateSignature(
                ConvertToStubType(meth.ReturnParameter.ParameterType),
                meth.IsStatic ? ConvertToStubTypes(Util.MapParametersToTypes(meth.GetParameters())) :
                Util.ConcatArray <Type>(
                    ConvertToStubType(meth.DeclaringType),
                    ConvertToStubTypes(Util.MapParametersToTypes(meth.GetParameters()))));

            return(GenerateDynamicMethod(classType.Name + "_" + meth.Name, methodSignature,
                                         delegate(ILGenerator ilg)
            {
                // Load (and unmarshal), the arguments to the method stub, then call the real method
                if (meth.IsStatic)
                {
                    EmitParameterLoading(ilg, 0, meth.GetParameters());
                    ilg.Emit(OpCodes.Call, meth);
                }
                else
                {
                    EmitParameterLoading(ilg, 0, meth.DeclaringType);
                    EmitParameterLoading(ilg, 1, meth.GetParameters());
                    ilg.Emit(OpCodes.Callvirt, meth);
                }

                // Unmarshal and return the result
                EmitMarshaledReturn(ilg, meth.ReturnParameter);
            }));
        }
        public void Initialize(DelegateSignature func, bool showButtons)
        {
            if (minusButton != null)
            {
                minusButton.onClick.AddListener(MinusCallback);
                minusButton.gameObject.SetActive(false);
            }
            if (plusButton != null)
            {
                plusButton.onClick.AddListener(PlusCallback);
                if (showButtons)
                {
                    plusButton.gameObject.SetActive(false);
                }
            }

            buttonsDelegate = func;
        }
Exemple #5
0
        /// <summary>
        /// Returns a native function pointer to a stub method that retrieves the value
        /// of the given static or instance field.
        /// </summary>
        /// <remarks>
        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
        /// </remarks>
        public static IntPtr GenerateFieldGetStub(FieldInfo field)
        {
            // Signature of the stub method returned (as a delegate) by this function
            DelegateSignature methodSignature = new DelegateSignature(
                ConvertToStubType(field.FieldType),
                field.IsStatic ? Type.EmptyTypes : new Type[] { ConvertToStubType(field.DeclaringType) });

            return(GenerateDynamicMethod(field.DeclaringType.Name + "_field_get_" + field.Name, methodSignature,
                                         delegate(ILGenerator ilg)
            {
                if (field.IsStatic)
                {
                    if (field.IsLiteral)
                    {
                        // FIXME: Move literal calculation to the generator, and add
                        //        support for literal values in the bridge (i.e.
                        //        values other than 'Obj ObjectId's
                        object literalValue = field.GetRawConstantValue();
                        if (literalValue is Int32)
                        {
                            ilg.Emit(OpCodes.Ldc_I4, (Int32)literalValue);
                        }
                    }
                    else
                    {
                        ilg.Emit(OpCodes.Ldsfld, field);
                    }
                }
                else
                {
                    // Load (and unmarshal) the argument to the method stub, then load the field value
                    EmitParameterLoading(ilg, 0, field.DeclaringType);
                    ilg.Emit(OpCodes.Ldfld, field);
                }

                // Unmarshal and return the result
                EmitToStub(ilg, field.FieldType);
                ilg.Emit(OpCodes.Ret);
            }));
        }
Exemple #6
0
        /// <summary>
        /// Instantiates a delegate that, given an IntPtr to a Haskell function, returns a
        /// delegate instance (of the given delegate type) that wraps this native function
        /// (and deals with parameter value marshaling and finalization).
        /// </summary>
        /// <param name="delegateType">Type of delegate returned by the returned delegate.</param>
        /// <returns>
        /// Wrapper delegate that accepts an IntPtr and returns a delegate of the
        /// indicated type.
        /// </returns>
        public static IntPtr GenerateDelegateConstructorStub(Type delegateType)
        {
            // Obtain (creating, if necessary) the type of a wrapper class for the delegate
            Type wrapperType = GetDelegateWrapperType(delegateType);

            DelegateSignature delegateSignature = DelegateSignature.FromDelegateType(delegateType);

            // Generate a dynamic method that does the following:
            //
            //     Int32 [delegateType]New(IntPtr funPtr)
            //     {
            //         [wrapperType] wrapper = new [wrapperType](funPtr);
            //         Delegate d = new [delegateType](wrapper.Invoke);
            //         return Driver.RegisterObject(d);
            //     }

            // Signature of the method returned (as a delegate) by this function (the
            // method accepts an IntPtr to a Haskell function and returns an instantiated
            // .NET delegate for it)
            DelegateSignature methodSignature = new DelegateSignature(
                typeof(Int32), new Type[] { typeof(IntPtr) });

            return(GenerateDynamicMethod(delegateType.Name + "New", methodSignature,
                                         delegate(ILGenerator ilg)
            {
                // wrapper = new [wrapperType](funPtr):
                ilg.Emit(OpCodes.Ldarg_0);
                ilg.Emit(OpCodes.Newobj, wrapperType.GetConstructor(new Type[] { typeof(IntPtr) }));

                // Obtain wrapper.Invoke
                ilg.Emit(OpCodes.Ldftn, wrapperType.GetMethod("Invoke"));

                // Delegate d = new [delegateType](wrapper.Invoke):
                ilg.Emit(OpCodes.Newobj, delegateType.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }));

                // return Driver.RegisterObject(d):
                ilg.Emit(OpCodes.Call, MemberInfos.Driver_RegisterObject);
                ilg.Emit(OpCodes.Ret);
            }));
        }
Exemple #7
0
        /// <summary>
        /// Returns a native function pointer to a stub method that returns a
        /// reference to the given value (boxing value types as necessary).
        /// </summary>
        /// <remarks>
        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
        /// </remarks>
        public static IntPtr GenerateBoxStub(Type typeToBox)
        {
            // Signature of the stub method returned (as a delegate) by this function
            DelegateSignature methodSignature = new DelegateSignature(
                typeof(Int32), new Type[] { ConvertToStubType(typeToBox) });

            return(GenerateDynamicMethod("box_" + typeToBox.Name, methodSignature,
                                         delegate(ILGenerator ilg)
            {
                // Load the (unboxed) value
                EmitParameterLoading(ilg, 0, typeToBox);

                if (typeToBox.IsValueType)
                {
                    // Box the type value to as an object
                    ilg.Emit(OpCodes.Box, typeToBox);
                }

                // Marshal the object instance out as an object index
                EmitToStub(ilg, typeof(object));
                ilg.Emit(OpCodes.Ret);
            }));
        }
Exemple #8
0
        /// <summary>
        /// Generates a dynamic method of the given name and signature, containing the instructions
        /// produced by 'ilWriter'.  A delegate to the method, is returned to the caller as a native
        /// function pointer.
        /// </summary>
        /// <remarks>
        /// This method also writes the method to the 'Stubs' class in 'Dynamic.dll' for debugging
        /// purposes.
        /// </remarks>
        private static IntPtr GenerateDynamicMethod(string methodName,
                                                    DelegateSignature methodSignature, ILWriterDelegate ilWriter)
        {
            if (true)
            {
                // Optional: generate an implementation of the stub method inside the 'Stubs'
                //           class (which is saved to 'Dynamic.dll') for debugging purposes.
                MethodBuilder savedMethod = _stubsTypeBuilder.DefineMethod(methodName, MethodAttributes.Public,
                                                                           methodSignature.ReturnType, methodSignature.ParameterTypes);
                ilWriter(savedMethod.GetILGenerator());
            }

            // Generate a dynamic method of the given name and signature, and the
            // IL instructions given by 'ilWriter', then return a delegate to the
            // method as a function pointer.

            // [stubReturnType] [classType]_[methodname]([classType] this, [args...]):
            DynamicMethod method = new DynamicMethod(methodName, methodSignature.ReturnType,
                                                     methodSignature.ParameterTypes, typeof(Driver));

            ilWriter(method.GetILGenerator());

            return(GetDotNetFunPtrForDelegate(method.CreateDelegate(methodSignature.ToDelegateType())));
        }
        public static void Main(string[] argv)
        {
            DelegateSignature delegateSignature = new DelegateSignature(DelegateFunction);

            delegateSignature();
        }
Exemple #10
0
        /// <summary>
        /// Creates (and returns the type of) a class that wraps a pointer to a
        /// Haskell function as a .NET delegate.  The class ensures that the
        /// wrapper function pointer is freed when the delegate is no longer being
        /// used by .NET.  It also performs any translation from .NET values to
        /// interop values (object references are converted to object identifiers).
        /// </summary>
        /// <param name="delegateType">Type of delegate produced by the wrapper</param>
        private static Type CreateDelegateWrapperType(string name, Type delegateType)
        {
            // Obtain the signature of the delegate being produced
            DelegateSignature delegateSignature = DelegateSignature.FromDelegateType(delegateType);

            // Obtain the delegate type of the associated thunk for calling into Haskell
            Type thunkDelegateType = new DelegateSignature(
                ConvertToStubType(delegateSignature.ReturnType),
                ConvertToStubTypes(delegateSignature.ParameterTypes)).ToDelegateType();

            TypeBuilder typeBuilder = _dynamicModuleBuilder.DefineType(name,
                                                                       TypeAttributes.Public | TypeAttributes.Sealed);

            // Define the _thunkDelegate field
            FieldBuilder thunkDelegateField = typeBuilder.DefineField("_thunkDelegate",
                                                                      thunkDelegateType, FieldAttributes.Private);

            {
                // Define the constructor for the wrapper type:
                //
                //     public DelegateWrapper(IntPtr funPtrToWrap)
                //     {
                //         _thunkDelegate = (ThunkDelegate)
                //             Marshal.GetDelegateForFunctionPointer(
                //                 funPtrToWrap, typeof(ThunkDelegate));
                //     }

                ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
                    MethodAttributes.Public | MethodAttributes.RTSpecialName,
                    CallingConventions.Standard, new Type[] { typeof(IntPtr) });
                ILGenerator ilg = constructorBuilder.GetILGenerator();

                // Call Object's constructor
                ilg.Emit(OpCodes.Ldarg_0);
                ilg.Emit(OpCodes.Call, MemberInfos.Object_ctor);

                ilg.Emit(OpCodes.Ldarg_0);                    // Load this (for the 'stfld' below)
                ilg.Emit(OpCodes.Ldarg_1);                    // Load funPtrToWrap

                ilg.Emit(OpCodes.Ldtoken, thunkDelegateType); // Load typeof(ThunkDelegate)
                ilg.Emit(OpCodes.Call, MemberInfos.Type_GetTypeFromHandle);

                // Call (ThunkDelegate)Marshal.GetDelegateForFunctionPointer(
                //          funPtrToWrap, typeof(ThunkDelegate))
                ilg.Emit(OpCodes.Call, MemberInfos.Marshal_GetDelegateForFunctionPointer);
                ilg.Emit(OpCodes.Castclass, thunkDelegateType);

                // Store in _thunkDelegate
                ilg.Emit(OpCodes.Stfld, thunkDelegateField);

                ilg.Emit(OpCodes.Ret);
            }

            {
                // Define a Finalize method for the wrapper class:
                //
                //     ~Delegate()
                //     {
                //         if (Driver.FreeHaskellFunPtr != null)
                //             Driver.FreeHaskellFunPtr(Marshal.GetFunctionPointerForDelegate(
                //                 _thunkDelegate));
                //     }

                MethodBuilder finalizeMethod = typeBuilder.DefineMethod("Finalize",
                                                                        MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual);
                finalizeMethod.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
                ILGenerator ilg      = finalizeMethod.GetILGenerator();
                Label       endLabel = ilg.DefineLabel();

                // Obtain the freeHaskellFunPtr delegate
                ilg.Emit(OpCodes.Ldsfld, MemberInfos.Driver_FreeHaskellFunPtr);

                // Return immediately if the delegate is null
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Beq, endLabel);

                // Obtain the freeHaskellFunPtr delegate (again)
                ilg.Emit(OpCodes.Ldsfld, MemberInfos.Driver_FreeHaskellFunPtr);

                // Load _thunkDelegate
                ilg.Emit(OpCodes.Ldarg_0);
                ilg.Emit(OpCodes.Ldfld, thunkDelegateField);

                // Call Marshal.GetFunctionPointerForDelegate to obtain the original function pointerusing
                ilg.Emit(OpCodes.Call, MemberInfos.Marshal_GetFunctionPointerForDelegate);

                // Invoke freeHaskellFunPtr on this function pointer
                ilg.Emit(OpCodes.Call, MemberInfos.FreeHaskellFunPtrDelegate_Invoke);

                ilg.MarkLabel(endLabel);
                ilg.Emit(OpCodes.Ret);
            }

            {
                // Define an Invoke method that calls _thunkDelegate after marshaling
                // the arguments as necessary:
                //
                //    private void Invoke(...)
                //    {
                //        _thunkDelegate(... using RegisterObject as appropriate ...);
                //    }

                MethodBuilder invokeMethod = typeBuilder.DefineMethod("Invoke",
                                                                      MethodAttributes.Public, delegateSignature.ReturnType, delegateSignature.ParameterTypes);
                ILGenerator ilg = invokeMethod.GetILGenerator();

                // Load _thunkDelegate (for calling it later)
                ilg.Emit(OpCodes.Ldarg_0);
                ilg.Emit(OpCodes.Ldfld, thunkDelegateField);

                // Load the parameters (and marshal according to type)
                for (int i = 0; i < delegateSignature.ParameterTypes.Length; i++)
                {
                    Util.EmitLdarg(ilg, i + 1);
                    EmitToStub(ilg, delegateSignature.ParameterTypes[i]);
                }

                ilg.Emit(OpCodes.Callvirt, thunkDelegateType.GetMethod("Invoke"));
                EmitFromStub(ilg, delegateSignature.ReturnType);
                ilg.Emit(OpCodes.Ret);
            }

            return(typeBuilder.CreateType());
        }
Exemple #11
0
        public static void Main()
        {
            DelegateSignature delegateSignature = new DelegateSignature(DelegateFunction);

            delegateSignature();
        }