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

最近在项目中碰到需要调用非托管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);
   }

你可能感兴趣的:(C++,String,C#,dll,button,引擎)