C#动态调用C++生成的dll

C++中的方法int MyFun(int a,int b);
生成dll文件:MyDll.dll

在C#中调用dll文件一般需要声明:
    [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int MyFun( int a, int b);
这样想动态来加载dll没办法操作。

后来在网上查了下,有两种方式能够动态的加载dll,不用声明:

先准备好DllInvoke类
 public class DllInvoke
    {
        #region Win API
        [DllImport("kernel32.dll")]
        private extern static IntPtr LoadLibrary(string path);

        [DllImport("kernel32.dll")]
        private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);

        [DllImport("kernel32.dll")]
        private extern static bool FreeLibrary(IntPtr lib);
        #endregion

        private IntPtr hLib;
        public DllInvoke(String DLLPath)
        {
            hLib = LoadLibrary(DLLPath);
            if (hLib == IntPtr.Zero)
            {
                throw (new Exception("没有找到:" + DLLPath + "。"));
            }  
        }

        ~DllInvoke()
        {
            FreeLibrary(hLib);
        }
        public IntPtr GetIntPtr(string APIName)
        {
            IntPtr api = GetProcAddress(hLib, APIName); 
            if (api == IntPtr.Zero)
            {
                throw (new Exception(" 没有找到 :" + APIName + " 这个函数的入口点 "));
            } 
            return api;
        }
        //将要执行的函数转换为委托
        public Delegate GetDelegate(string APIName, Type t)
        {
            IntPtr api =GetIntPtr(APIName);
            return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);
        }
    }



方法一:
delegate int Add(IntPtr[] X, int r, int c);

 
 DllInvoke dk = new DllInvoke("MyDll.dll");
 Add addFunction = (Add)dk.GetDelegate("MyFun", typeof(Add));
int sum=addFunction(2,3);



方法二:
object[] par = new object[] {2,3 };//输入参数
Type[] parType = par.Select(s=>s.GetType()).ToArray();//输入参数的类型
//Type[] parType =new Type[]{typeof(int),typeof(int)};
Type Type_Return = typeof(int); // 返回类型
 
AssemblyName assemblyName = new AssemblyName("InvokeName");//名称随便写
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("InvokeModule");
MethodBuilder methodBuilder = moduleBuilder.DefineGlobalMethod("InvokeMethod", MethodAttributes.Public | MethodAttributes.Static, Type_Return, parType);
ILGenerator IL = methodBuilder.GetILGenerator();
for (int i = 0; i < par.Length; i++)
           {// 依次压入堆栈  
               IL.Emit(OpCodes.Ldarg, i);   //实参传送方式,byValue 
               //    IL.Emit(OpCodes.Ldarga, i);//实参传送方式,byRef 
           }
//要调用的dll
           DllInvoke dk = new DllInvoke("MyDll.dll");
//调用的方法
           IntPtr farProc = dk.GetIntPtr("MyFun");
           if (IntPtr.Size == 4)
           {// 判断处理器类型
               IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());
           }
           else if (IntPtr.Size == 8)
           {
               IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());
           }
           else
           {
               throw new PlatformNotSupportedException();
           }
           IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, parType);
           IL.Emit(OpCodes.Ret);
           moduleBuilder.CreateGlobalFunctions();
//方法名和上面的一致
           MethodInfo MyMethodInfo = moduleBuilder.GetMethod("InvokeMethod");
           object sum = MyMethodInfo.Invoke(null, par);// 调用方法,并返回其值

猜你喜欢

转载自diwuci.iteye.com/blog/2372475