从 C# 代码调用 delphi DLL 函数

Posted

技术标签:

【中文标题】从 C# 代码调用 delphi DLL 函数【英文标题】:Calling a delphi DLL function from C# Code 【发布时间】:2011-12-28 08:20:52 【问题描述】:

我有一个在 Delphi 2007 中编译的 DLL 和一个在其他 Delphi 项目中使用它的示例。下面是部分代码:

TErrorCallback = function(Msg:PChar):byte of object;
TSaveEventCallback = function (Line:PChar; HiCode:PChar; LoCode:PChar; MobileNo:PChar):byte of object;

function InitModule(ErrorCallback:TErrorCallback; SaveEventCallback :TSaveEventCallback; MainWindowHandle:THandle; Sock_Event:integer):byte; stdcall; external 'My.dll' name 'InitModule';

function DLLSocketEvent(var msg: TMessage): byte; stdcall; external 'My.dll' name 'DLLSocketEvent';

function InitObjList(Objs: array of PChar; NumObjs: byte; Name: PChar):byte; stdcall; external 'My.dll' name 'InitObjList';

这是我的 C# 类比:

class Message

  unsigned int msg;
  int wParam;
  int lParam;
  int result;
;
delegate byte ErrorCallbackDelegate(string msg);
delegate byte SaveEventCallbackDelegate(string line, string hiCode, string loCode, string mobileNo);

[DllImport("My.dll")]
static extern byte InitModule(ErrorCallbackDelegate errorCallback, SaveEventCallbackDelegate saveEventCallback, IntPtr mainWindowsHandle, Int32 sockEvent);

[DllImport("My.dll")]
static extern byte DllSocketEvent(Message msg);

[DllImport("My.dll")]
static extern byte InitObjList(string[] objs, byte numObjs, string name);

关键是我只尝试了 InitModule 方法,它抛出了一个异常: 调用 PInvoke 函数 'ProjTest!ProjTest.MyClass::InitModule' 使堆栈失衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。

请帮帮我。我应该如何在 C# 中描述这些 DLL 函数?

【问题讨论】:

【参考方案1】:

您不能从 C# 调用该 DLL。主要问题是两个of object 回调。 C# 中没有办法与之匹配。您将需要修改现有的 DLL 或添加中间适配器 DLL。就目前而言,您的 DLL 只能从 Delphi 或 C++ Builder 访问。

如果您可以修改 DLL,那么您需要进行的修改是删除 of object。如果您需要回调对实例进行操作,那么您需要将实例作为参数传递。但是,C# 委托可以透明地包装所有内容,因此如果您需要从其他语言访问 DLL,您只需将实例作为参数传递,例如德尔福。

另一个问题是开放数组参数。这也不容易从其他语言访问。虽然有tricks,但我建议传递对第一个元素的引用而不是开放数组。开数组是 Delphi 独有的。

我也不明白你为什么使用byte 类型来保存数组长度。您应该为此使用Integer。使用 byte 没有任何好处,您只需邀请溢出。另外,MainWindowHandle 在 Delphi 中不应该是 THandle。应该是HWND

我对您的建议是修改 DLL 以具有与 C 兼容的接口,从而可以从支持该接口的所有语言访问。实际上,这将使所有主流编程语言都可以访问它。

【讨论】:

以上是关于从 C# 代码调用 delphi DLL 函数的主要内容,如果未能解决你的问题,请参考以下文章

从 Delphi“访问冲突”正确调用 DLL 中的 C++ 函数

从 C# 调用时,是不是可以获得 Kernel32.dll 函数的最后一个错误代码?

c#调用Delphi DLL参数为结构体数组

从Delphi调用C ++ DLL时发生访问冲突

Delphi程序怎么调用C#写的dll类库

尝试从 VS2013 C# 程序调用 DELPHI XE2 DLL 时出错