C#种动态加载C++的DLL

    技术2022-05-20  31

    最近在项目中碰到需要调用非托管C++生成的dll,下面将自己遇到的问题,以及解决的办法总结如下:  1.     问题:     我们通常去映射dll的方法是使用

            public   const   string  dllPath  = path;                [DllImport(dllPath  +   " test.dll " , EntryPoint  =   " test() " , SetLastError  =   true ,          CharSet  =  CharSet.Ansi, ExactSpelling  =   true , CallingConvention  =  CallingConvention.Cdecl)]          public   static   extern   int test();

         这种方式有一个致命的缺陷,dll文件路径dllPath必须为const,而const是编译时常量,也就是说dllPath赋值必须是字符串常量,如果你想动态指定dll文件路径用这种方式基本上没办法实现,下面是一种解决方案。     解决方案:

            [DllImport( " Kernel32.dll " )]         public   static   extern  IntPtr LoadLibrary( string  lpFileName);        [DllImport( " kernel32.dll " , SetLastError  =   true )]         public   static   extern   int  GetProcAddress(            IntPtr hModule,  string  lpProcName);        [DllImport( " kernel32.dll " , EntryPoint  =   " FreeLibrary " , SetLastError  =   true )]         public   static   extern   bool  FreeLibrary(IntPtr hModule);

         这种方式有点像C#的反射,先引入这3个API 函数:     LoadLibrary(string lpFileName)是加载指定的dll文件,参数lpFileName为dll文件的路径,返回的为该dll的实例(指针)             GetProcAddress(IntPtr hModule,string lpProcName)是获取dll中指定的方法委托,参数hModule为LoadLibrary()方法返回的值,lpProcName方法名,返回值为指定方法的委托,注意要强制转换.     FreeLibrary(InPtr hModule)是释放加载的dll文件,参数hModule为LoadLibrary()返回值.     有了这些方法就能很容易的实现动态加载dll。     代码:    

             // dll实例          static   private  IntPtr instance;         // 要加载方法的委托          delegate   void  Test();          // 导入引擎dll         [DllImport( " Kernel32.dll " )]         public   static   extern  IntPtr LoadLibrary( string  lpFileName);        [DllImport( " kernel32.dll " , SetLastError  =   true )]         public   static   extern   int  GetProcAddress(            IntPtr hModule,  string  lpProcName);        [DllImport(" kernel32.dll " , EntryPoint  =   " FreeLibrary " , SetLastError  =   true)]         public   static   extern   bool FreeLibrary(IntPtr hModule);         // 获取方法指针         static   private  Delegate GetAddress(IntPtr dllModule,  string functionname, Type t)        {            int addr = GetProcAddress(instance, functionname);            if (addr == 0)                return null;            else                return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t);        }         // 加载DLL         static   public   void LoadLib()        {            string dllPath;            dllPath = ConfigurationSettings.AppSettings["dllPath"].ToString();            instance = LoadLibrary(dllPath);            if (instance.ToInt32() == 0)            {                throw new LoadLibraryException("请在App.Config中配置引擎DLL的路径!");            }        }          /// <summary>        /// 卸载DLL        /// </summary>          static   public   void FreeLib()        {            FreeLibrary(instance);        }          /// <summary>        /// 实例        /// </summary>        /// <param name="iptr"></param>        /// <returns></returns>          static   public   void test()        {            try            {                Test temp = (Test)GetAddress(instance, "test"typeof(Test));                return temp();            }            catch (Exception ex)            {                throw new LoadLibraryException("");            }

            }

    public delegate int MsgBox(int hwnd,string msg,string cpp,int ok);   [DllImport("Kernel32")]   public static extern int GetProcAddress(int handle, String funcname);   [DllImport("Kernel32")]   public static extern int LoadLibrary(String funcname);   [DllImport("Kernel32")]   public static extern int FreeLibrary(int handle);   private static Delegate GetAddress(int dllModule, string functionname, Type t)   {   int addr = GetProcAddress(dllModule, functionname);   if (addr == 0)   return null;   else   return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t);   }   private void button1_Click(object sender, EventArgs e)   {   int huser32 = 0;   huser32 = LoadLibrary("user32.dll");   MsgBox mymsg = (MsgBox)GetAddress(huser32, "MessageBoxA", typeof(MsgBox));   mymsg(this.Handle.ToInt32(), txtmsg.Text, txttitle.Text , 64);   FreeLibrary(huser32);   }


    最新回复(0)