2
votes

So I learned using IntPtr in this case,

-delphi (delphi 2006 version) code

 function GetRequestResult(out code:integer):PChar; stdcall;
   begin
    LogMessage('GetRequestResult');
    code:=requestCode;
    result:=PChar(RequestResult);
    LogMessage('GetRequestResult done');
   end;

then, for using in c#, I used like,

IntPtr str = GetRequestResult(out code); 
string loginResult = Marshal.PtrToStringAnsi(str); 

and this works well.

Then, how about this case?

-delphi code

 procedure Login(login,password:PChar); stdcall;
...
...

this PChar is inside (). So what is exact way to pass string value to that Login delphi function?

[DllImport ("ServerTool")]

  1. private static extern void Login([MarshalAs(UnmanagedType.LPStr)]string id, [MarshalAs(UnmanagedType.LPStr)]string pass);

  2. private static extern void Login(IntPtr id, IntPtr pass); // in this case, how use this IntPtr in latter part?

  3. private static extern void Login(string id, string pass);

Thanks in advance.

2
What delphi version? Since this is primarily a C# question, I would suggest you refer only to PAnsiChar (which is always equivalent to char * type in C, regardless of Delphi version) on stackoverflow, if the underlying DLL is delphi 7 dll, or XE then the signature you've listed above would have two different meanings.Warren P

2 Answers

3
votes

Your option 3 is the correct way to do this. The p/invoke marshaller will map a C# string to a pointer to null terminated character array, i.e. PChar. The default calling convention is stdcall, and the default character set is Ansi and so you don't need to specify those.

Your option 1 works also but is unnecessarily verbose since you are just re-stating the default marshalling. Option 2 could work also but you'd just be creating extra work for yourself. You'd have the responsibility of freeing the IntPtr values once the native function call returned.