首先,由于您没有说明使用的是哪个 Delphi 版本,我将假设您使用的是 Delphi 6,原因是我熟悉它。
您的 Delphi 程序在声明中没有指定调用约定,因此它不会使用 stdcall,而是使用默认的 Delphi register 调用约定,该约定将前几个参数放在寄存器中而不是堆栈上。如果您可以更改 Delphi DLL,则在声明后添加 stdcall; 并重新构建,这样您的调用约定就会匹配。
下表总结了调用约定。
Directive Parameter order Clean-up Passes parameters in registers?
--------- --------------- -------- -------------------------------
register Left-to-right Routine Yes
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No
safecall Right-to-left Routine No
查看.NET文档,似乎没有与Delphi的register调用约定相匹配的约定(请参见下表),因此我认为你唯一的选择可能是在Delphi DLL中更改约定。
Member name Description
----------- ------------------------
Cdecl The caller cleans the stack. This enables calling functions with varargs, which makes it appropriate to use for methods that accept a variable number of parameters, such as Printf.
FastCall This calling convention is not supported.
StdCall The callee cleans the stack. This is the default convention for calling unmanaged functions with platform invoke.
ThisCall The first parameter is the this pointer and is stored in register ECX. Other parameters are pushed on the stack. This calling convention is used to call methods on classes exported from an unmanaged DLL.
Winapi Supported by the .NET Compact Framework. This member is not actually a calling convention, but instead uses the default platform calling convention. For example, on Windows the default is StdCall and on Windows CE .NET it is Cdecl.
你的Delphi(6)PChar(指向以 null 结尾的 ANSI 字符串的指针)编组看起来正确。