问题描述
我在德尔福2007年编制了DLL和其他德尔福的项目中使用它的一个例子。下面是部分代码:
I have a DLL compiled in Delphi 2007 and an example using it in other Delphi project. Here is a part of code:
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#模拟:
And here is my C# analog:
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签名的调用约定和参数与非托管的目标签名。
The point is I've tried only InitModule method and it throwed an exception:A call to PInvoke function 'ProjTest!ProjTest.MyClass::InitModule' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
请帮我与此有关。我应该如何在C#中描述这些DLL函数?
Please, help me with this. How should I describe these DLL functions in C#?
推荐答案
您不能调用从C#该DLL。主要的问题是两个对象
回调。有没有在C#中没有办法匹配。您将需要修改现有的DLL或增加中间适配器DLL。因为它代表你的DLL是德尔福或C ++ Builder才能访问。
You can't call that DLL from C#. The main problem are the two of object
callbacks. There's no way in C# to match that. You will need to modify the existing DLL or add an intermediate adapter DLL. As it stands your DLL is only accessible from Delphi or C++ Builder.
如果您可以修改DLL,那么你需要做的修改是删除对象
。如果你需要回调作用于一个实例,那么你将需要通过实例作为参数。然而,C#代表可以包装所有的透明起来,所以你只需要通过实例作为一个参数,如果你需要的DLL是从其他语言,例如访问德尔福。
If you can modify the DLL then the modification you need to make is to remove the of object
. If you need the callback to act on an instance then you will need to pass the instance as a parameter. However, C# delegates can wrap all that up transparently so you would only need to pass the instance as a parameter if you needed the DLL to be accessible from other languages, e.g. Delphi.
另一个问题是开放数组参数。那也是不容易从其他语言访问。虽然有的招数,我会建议传递引用的第一个元素,而不是一个开放的阵列。开放数组是唯一的德尔福。
The other issue is the open array parameter. That is also not easily accessed from other languages. Although there are tricks, I would recommend passing a reference to the first element rather than an open array. Open arrays are unique to Delphi.
我也想不明白,为什么你使用的是字节
键入持有阵列长度。您应该使用整数
这一点。没有什么使用字节来获得你根本邀请溢出。此外, MainWindowHandle
不应该 THandle
Delphi中。它应该是 HWND
。
I also do not understand why you are using the byte
type to hold array length. You should use Integer
for this. There's nothing to gain from using byte and you simply invite overflow. Also, MainWindowHandle
should not be THandle
in Delphi. It should be HWND
.
我给你的建议是修改DLL有一个C兼容接口和因此,从支持所有语言的访问。在实践中,这将使所有主流编程语言访问。
My recommendation to you would be to modify the DLL to have a C compatible interface and thus be accessible from all languages that support that. In practice this would make it accessible from all mainstream programming languages.
这篇关于从调用C#代码德尔福DLL函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!