1

I'm trying to rewrite a code from C# based on a DLL (maybe also from C#, I don't have source/doc from it), in Delphi 10.3. But I'm facing some problems around a string field... Here is the working code from C#:

[DllImport("methods.dll", CharSet = CharSet.Ansi)] 
public static extern int getName([MarshalAs(UnmanagedType.LPStr)] ref string apstrName);

string myName = "";
int ret = getName(ref myName);

"ret" gets "0" and "myName" gets "ok".

In Delphi, I've tried:

function getName(var apstrName: PAnsiChar): Integer; stdcall; external 'methods.dll';

var myName: PAnsiChar;

ret := getName(myName);

But "ret" gets "-1" (invalid parameter) and "myName" gets "#0" (null).

I've tried other types instead PAnsiChar: PChar, PWideChar, PByte, string, AnsiString, WideString... No success!

Do you have any clue what's wrong here?

Thanks a lot!

peaga_br
  • 11
  • 2
  • I think you must pass a BSTR. See https://learn.microsoft.com/en-us/previous-versions/windows/desktop/automat/bstr. – fpiette Dec 13 '20 at 20:26
  • 1
    @fpiette That is not correct. The PInvoke is clearly passing an null-terminated C-style ANSI string pointer by reference. A BSTR does not match that. Not even close. – Remy Lebeau Dec 13 '20 at 20:29
  • @peaga_br the Delphi code looks correct to me, based on the C# code. Though I’m surprised the C# code even works, since `string` is immutable so the DLL shouldn’t be able to modify it. Do you happen to have a C/C++ header file for the DLL, or any documentation for it, so we can see the actual function declaration and requirements? – Remy Lebeau Dec 13 '20 at 20:31
  • Who allocates the memory here? The C# signature is ref so it should probably be allocated first? Or should it be out and should dll allocate it? But in that case, who frees it?? – Remko Dec 13 '20 at 22:00
  • For this to work you would need to pass an IntPtr by ref and have the callee allocate a null terminated character array on the COM heap. – David Heffernan Dec 13 '20 at 22:06
  • Why specifically the COM heap, it just needs to be allocated somewhere? – Remko Dec 13 '20 at 22:12
  • @remko Because the C# marshaler is tasked with deallocating it, and so the two parties need to agree on which heap to use. – David Heffernan Dec 14 '20 at 03:12
  • As I understood it @david the shown c# code is also calling the dll of which we don’t know if it was written in c# (most likely not as it’s exposing a c style string) – Remko Dec 14 '20 at 21:29
  • @Remko It doesn't matter what it was written in. The point is that knowing the C# side of the interface fixes the contract. The C# code is going to call CoTaskMemFree on the pointer returned. – David Heffernan Dec 14 '20 at 22:06
  • that assumes that the c# code is correct of which I'm not entirely sure – Remko Dec 14 '20 at 22:30
  • @remko Well, the questions states that the C# code is working. If that fact is incorrect then we have nothing. – David Heffernan Dec 15 '20 at 08:02
  • Hi guys, thanks for your help! Just answering some questions, this DLL is from a time attendance device, used for TCP/IP communication. I only have a working demo on C# (with source code) and I've just found a chinese doc with "apstrName" declared as "BSTR*". But I think this doc is outdated, as there're some methods on DLL not present on it... – peaga_br Dec 20 '20 at 22:36

0 Answers0