将 Pchar Delphi DLL 导入 C#?

发布于 2024-10-18 16:33:38 字数 1059 浏览 4 评论 0原文

我在delphi中有一个程序:

procedure PasswordDLL(month  integer; password  pchar); 
export;

该程序应该将密码输出到我传入的“password”pchar。 从我谷歌......和阅读...... 参考:此处这里

我想出:

[DllImport(
    "DelphiPassword.dll",
    CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi,
EntryPoint = "PasswordDLL")]
public static extern void PasswordDLL(    
    int month,
    [MarshalAs(UnmanagedType.LPStr)] string password
    ); 

然后当我调用时:

string pass = "";
PasswordDLL(2, pass);

所以密码要输出到“pass”字符串。

但我会得到 BadImageFormatException was unhandled: An attempts was made to load a program with an invalid format. (HRESULT 异常:0x8007000B)

听起来我使用的函数格式是错误的? 我想知道我是否对 PChar 使用了不正确的 UnmanagedType,但从阅读来看,它要么是 LPWStr,要么是 LPStr。我错过了什么吗?

提前致谢...

I have a procedure in delphi:

procedure PasswordDLL(month  integer; password  pchar); 
export;

The procedure should output the password to "password" pchar that I passed in..
From what I google..and reading....
ref: HERE and HERE

I come up with:

[DllImport(
    "DelphiPassword.dll",
    CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi,
EntryPoint = "PasswordDLL")]
public static extern void PasswordDLL(    
    int month,
    [MarshalAs(UnmanagedType.LPStr)] string password
    ); 

Then when I call:

string pass = "";
PasswordDLL(2, pass);

So the password to output to the "pass" string.

But I will get BadImageFormatException was unhandled: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)

Sounds the function format I used is wrong?
I wonder if I used incorrect UnmanagedType for PChar, but from the reading, it is either LPWStr and LPStr.. Did I missed something?

Thanks in advance...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花桑 2024-10-25 16:33:38

首先,由于您没有说明您使用的是哪个 Delphi 版本,所以我将假设 Delphi 6 回答,没有其他原因,除了我熟悉它。

您的 Delphi 过程在其声明中未指定调用约定,因此它不会根据您的导入使用stdcall。它将使用默认的 Delphi register 约定,将前几个参数放置在寄存器中而不是堆栈上。如果您可以更改 Delhpi 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(指向空终止 ANSI 字符串的指针)编组看起来正确。

First off Since you have not stated which Delphi version your using I will answer assuming Delphi 6 for no other reason than I am familiar with it.

Your Delphi procedure does not specify a calling convention in its declaration, so it won't be using stdcall as per your import. It will use the default Delphi register convention which places the first few parameters in registers rather than on the stack. If you can change your Delhpi DLL add stdcall; after the declaration and rebuild and your calling conventions will match.

The table below summarizes calling conventions.

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

Looking at the .NET documentation there does not seem to be a calling convention that matches Delphi's register convention (see table below) so I think your only option may be to change convention in the 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.

Your Delphi (6) Pchar (pointer to a null terminated ANSI string) marshalling looks correct.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文