C#调用非托管dll的两种方式

avatar
作者
筋斗云
阅读量:3

C#调用非托管DLL的两种方式

在开发过程中,我们经常需要调用一些非托管的DLL库,比如用Delphi编写的DLL。本文将介绍两种在C#中调用非托管DLL的方法。

示例DLL

首先,我们有一个Delphi编写的DLL,它导出了一个名为MyFunction的方法:

library testDLL;  uses   SysUtils,   Dialogs,   Classes;  {$R *.res}  function MyFunction(param1: Integer): Integer; stdcall; begin   Result := param1 + 1; end;  exports   MyFunction;  begin end. 

方式一:直接调用

这是最常见的调用方式,通过DllImport属性直接导入非托管方法。

[DllImport("testDLL.dll")] static extern int MyFunction(int a); 

然后,你可以直接调用这个方法:

int i = MyFunction(123); 

方式二:使用本地委托

另一种方法是将非托管方法转换为本地委托。这种方式更灵活,但需要更多的代码。

辅助方法

首先,我们需要一些辅助方法来加载和卸载DLL:

// 辅助方法:加载DLL [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr LoadLibrary(string lpFileName);  // 辅助方法:卸载DLL [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool FreeLibrary(IntPtr hModule);  // 获取方法指针 [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); 

定义委托

接下来,定义一个与DLL中方法参数一致的委托:

public delegate int MyFunctionDelphiDelegate(int param1); 

使用委托调用方法

最后,使用委托来调用非托管方法:

void run() {     // 加载DLL     IntPtr dllHandle = LoadLibrary("testDLL.dll");     if (dllHandle == IntPtr.Zero)     {         var err = Marshal.GetHRForLastWin32Error();     }      // 获取方法指针     IntPtr functionPointer = GetProcAddress(dllHandle, "MyFunction");      MyFunctionDelphiDelegate my = (MyFunctionDelphiDelegate)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(MyFunctionDelphiDelegate));     // 调用方法     int i = my(1);      // 释放DLL     FreeLibrary(dllHandle); } 

注意事项

  1. 位数一致性:确保你的程序和DLL的位数(32位或64位)保持一致。
  2. 字符串参数:Delphi方法中的参数和返回值如果是字符串,不能直接使用String类型。需要使用PAnsiCharPChar,并搭配StrNew使用。
  3. 返回值:如果方法返回值为字符串,需要使用IntPtr类型,并通过Marshal.PtrToStringAnsi(strIntPtr)来获取实际的字符串值。

通过这两种方式,你可以灵活地在C#中调用非托管的DLL库,满足不同的开发需求。


广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!