从C#代码调用Delphi DLL函数

7

我有一个使用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个回答

11
您无法从C#调用该DLL。主要问题是两个“of object”回调。在C#中没有办法匹配它。您需要修改现有的DLL或添加一个中间适配器DLL。目前,您的DLL仅可从Delphi或C++ Builder访问。
如果您可以修改DLL,则需要进行的修改是删除“of object”。如果需要回调作用于实例,则需要将实例作为参数传递。但是,C#委托可以将所有内容都包装起来,因此只需要在其他语言(例如Delphi)需要访问DLL时将实例作为参数传递。
另一个问题是开放数组参数。这在其他语言中也不容易访问。虽然有技巧,但我建议传递对第一个元素的引用而不是开放数组。开放数组是Delphi独有的。
我还不明白为什么要使用“byte”类型来保存数组长度。您应该使用“Integer”来代替。使用byte并没有什么好处,只会引发溢出。此外,在Delphi中,“MainWindowHandle”不应该是“THandle”,而应该是“HWND”。
我的建议是将DLL修改为具有C兼容接口,从而可以从支持该接口的所有语言访问它。实际上,这将使其从所有主流编程语言中都可以访问。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接