2011-02-23 113 views
4

我在德尔福的过程:我在通过将Pchar Delphi DLL导入C#?

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

的程序应该输出密码设置为“密码” PChar类型.. 从我读google..and .... REF:HEREHERE

我想出了:

[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未处理:试图加载一个格式不正确的程序。 (异常来自HRESULT:0x8007000B)

听起来我用的函数格式是错误的? 我不知道如果我使用不正确的UnmanagedType为PChar,但从阅读,它是LPWStr和LPStr ..我错过了什么?

在此先感谢...

回答

2

首先因为我们还没有说哪个版本的Delphi您使用我会回答假设德尔福6没有其他原因比我熟悉它。

您的德尔福程序没有在其声明中指定调用约定,所以根据您的导入,它不会使用stdcall。它将使用默认的德尔福寄存器约定,它将前几个参数放在寄存器中而不是堆栈中。如果你可以改变你的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 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字符串的指针)编组看起来正确。

+1

谢谢,您的总结帮助我理解。 :) – King 2011-02-23 16:16:42

+1

还有其他的东西会出错:PChar指向的缓冲区必须由调用者分配。否则,您将在退出时体验AV(最好)。你将需要添加一个参数来指定传递给dll的缓冲区的大小,确保它足够大以返回数据 - 包括空字符 - 否则返回一个错误。 – Stephane 2011-02-23 16:47:32

+0

辉煌,这解决了我正在用Delphi 5和C#完美查找的问题。非常赞赏皮特 – nrjohnstone 2013-06-21 22:25:23