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("");
            }

        } 

 

 

//mydll.cpp   
    
  int     f(int     a,     char*     b,     int*     c)     
  {   
  return(10);   
  }   
    
  //mydll.def   
  LIBRARY   MyDll   
    
  EXPORTS   
  f   @1   
    
    
  //c#   
  [DllImport("mydll.dll")]   
  public   static   extern   int   f(int   a,StringBuilder   b,ref   int   c);   
  static   void   Main(string[]   args)   
  {   
  StringBuilder   b=new   StringBuilder(10);   
  int   c=0;   
  Console.WriteLine("{0}",f(10,b,ref   c));   
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值