2011-12-28 153 views
7

我有一个在Delphi 2007中编译的DLL和一个在其他Delphi项目中使用它的例子。下面是部分代码:从C#调用delphi DLL函数代码

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函数?

回答

11

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

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

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

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

我向你推荐的方法是将DLL修改为具有C兼容接口,因此可以从支持该接口的所有语言访问。实际上,这将使其可以从所有主流编程语言访问。

+0

为什么选择投票? – 2011-12-28 09:38:11