从C#代码调用delphi DLL函数

从C#代码调用delphi DLL函数,c#,delphi,pinvoke,C#,Delphi,Pinvoke,我在Delphi2007中编译了一个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:TErro

我在Delphi2007中编译了一个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#模拟:

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


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

您不能从C#调用该DLL。主要问题是对象的两个
回调。在C#中没有办法与之匹配。您需要修改现有DLL或添加中间适配器DLL。正如你所说的,你的DLL只能从Delphi或C++ Builder访问。p>
如果可以修改DLL,则需要进行的修改是删除对象的
。如果需要回调对实例执行操作,则需要将实例作为参数传递。但是,C#委托可以透明地包装所有这些内容,因此,如果需要从其他语言(如Delphi)访问DLL,则只需将实例作为参数传递

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

我也不明白为什么要使用
字节
类型来保存数组长度。您应该使用
Integer
进行此操作。使用字节并没有什么好处,只会导致溢出。另外,在Delphi中,
MainWindowHandle
不应该是
THandle
。它应该是
HWND

我建议您修改DLL,使其具有与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);