Importing Pchar Delphi DLL to C#?

3k views Asked by At

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...

1

There are 1 answers

3
Pete Stensønes On BEST ANSWER

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.