Exemplo n.º 1
0
        // Returns implementation of a given interface for wrapping function the specified DLL
        public IT getInterface <IT> (string dll_name) where IT : class
        {
            lock (_sync_object)
            {
                Type itype = typeof(IT);
                // Check if such interface was already loaded
                WrappedInterface interf = null;
                if (!_loaded_dlls[dll_name].interfaces.TryGetValue(itype, out interf))
                {
                    interf = createInterface <IT>(dll_name);
                    _loaded_dlls[dll_name].interfaces.Add(itype, interf);
                }

                return((IT)interf.instance);
            }
        }
        // Creates implementation of a given interface for wrapping function the specified DLL
        WrappedInterface createInterface <IT>(string dll_name) where IT : class
        {
            WrappedInterface result = new WrappedInterface();

            Type         itype = typeof(IT);
            AppDomain    cd    = System.Threading.Thread.GetDomain();
            AssemblyName an    = new AssemblyName();

            an.Name = itype.Name + "_" + dll_name.Replace('.', '_');
            AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            ModuleBuilder   mb = ab.DefineDynamicModule(an.Name, false);
            TypeBuilder     tb = mb.DefineType(an.Name, TypeAttributes.Class |
                                               TypeAttributes.Public);

            tb.AddInterfaceImplementation(itype);

            IntPtr dll_handle = _loaded_dlls[dll_name].handle;

            Dictionary <List <Type>, Type> signature_to_name =
                new Dictionary <List <Type>, Type>(new TypeListComparer());

            // Set delegate references
            foreach (MethodInfo m in itype.GetMethods())
            {
                ParameterInfo[] parameters = m.GetParameters();
                Type[]          arg_types  = new Type[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    arg_types[i] = parameters[i].ParameterType;
                }

                Type delegate_ret_type = m.ReturnType;
                if (delegate_ret_type == typeof(String))
                {
                    delegate_ret_type = typeof(sbyte *);
                }

                List <Type> signature = new List <Type>();
                signature.Add(delegate_ret_type);
                signature.AddRange(arg_types);

                Type call_delegate = null;
                if (!signature_to_name.TryGetValue(signature, out call_delegate))
                {
                    // Check if type was already created
                    string delegate_type_name = String.Format("delegate_{0}", signature_to_name.Count);
                    call_delegate = createDelegateType(delegate_type_name, mb, delegate_ret_type, arg_types);
                    signature_to_name.Add(signature, call_delegate);
                }

                string       delegate_field_name = m.Name + "_ptr";
                FieldBuilder delegate_field      =
                    tb.DefineField(delegate_field_name, typeof(Delegate), FieldAttributes.Private);

                IntPtr proc = LibraryLoader.GetProcAddress(dll_handle, m.Name);
                if (proc == IntPtr.Zero)
                {
                    throw new IndigoException(String.Format("Cannot find procedure {0} in the library {1}",
                                                            m.Name, dll_name));
                }
                Delegate proc_delegate = Marshal.GetDelegateForFunctionPointer(proc, call_delegate);
                result.delegates.Add(delegate_field_name, proc_delegate);

                MethodBuilder meth = tb.DefineMethod(m.Name,
                                                     MethodAttributes.Public | MethodAttributes.Virtual, m.ReturnType, arg_types);

                ILGenerator il = meth.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, delegate_field);
                for (int i = 1; i < arg_types.Length + 1; i++)
                {
                    il.Emit(OpCodes.Ldarg, i);
                }
                MethodInfo infoMethod = proc_delegate.GetType().GetMethod("Invoke", arg_types);
                il.EmitCall(OpCodes.Callvirt, infoMethod, null);
                // Automatically convert sbyte* to String
                if (m.ReturnType == typeof(String))
                {
                    Type            str_type = typeof(String);
                    ConstructorInfo ci       = str_type.GetConstructor(new Type[] { typeof(sbyte *) });
                    il.Emit(OpCodes.Newobj, ci);
                }
                il.Emit(OpCodes.Ret);

                tb.DefineMethodOverride(meth, m);
            }

            // ab.Save(an.Name + ".dll");

            Type impl_class = tb.CreateType();
            IT   impl       = (IT)Activator.CreateInstance(impl_class);

            // Set references to the delegates
            foreach (string field_name in result.delegates.Keys)
            {
                impl_class.GetField(field_name, BindingFlags.Instance | BindingFlags.NonPublic)
                .SetValue(impl, result.delegates[field_name]);
            }

            result.instance = impl;
            return(result);
        }