Question

I have a c++ dll that I am using using Pinvoke.

The method signature is as follow:

c++:

EXTERN_C BOOL std_call MyCppMethod(LPCSTR param1, LPCSTR param2);

C#:

[DllImport("MyDll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool MyCppMethod(
         /*[MarshalAs(UnmanagedType.LPWStr)]*/ string param1,
         /*[MarshalAs(UnmanagedType.LPWStr)]*/ string param2
        );

for technical reasons I replaced the dll with a lib, and wrapped the lib with a dll that uses EXPORTS.def file and EXPORTS declaration to export the method from the lib. Since I have dine that I see a weird behavior. instead of getting the string in the method implementation I get only the first character.

I had tried to replace the calling convention, to use marshalAs LPCWSTR, and also tried to replace the lpcstr in the c++ decleration with char*. non of the above helped me to solve the problem and I still get only the first character.

Why this is happening and how can I solve this problem?

Was it helpful?

Solution

LPCSTR is a pointer to null-terminated array of char, and UnmanagedType.LPWStr is a pointer to null-terminated array of wchar_t. So there is a simple mis-match.

The reason why you only received a single character is that ASCII characters, when represented as two byte UTF-16 characters, have the ASCII value in one byte, and a zero in the other byte. When interpreted as null-terminated array of char, this is a string of length one. The zero byte is interpreted as the null-terminator.

You can fix it by changing either:

  1. LPCSTR to LPCWSTR on the native side, or
  2. UnmanagedType.LPWStr to UnmanagedType.LPStr on the managed side.

Frankly, to me it makes more sense to use Unicode these days so I would go for option 1. Indeed, since you specified CharSet.Unicode then there is no need for the MarshalAs at all. The code would look like this:

C++

BOOL std_call MyCppMethod(LPCWSTR param1, LPCWSTR param2);

C#

[DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
public static extern bool MyCppMethod(string param1, string param2);

Note that I am also sceptical of your setting SetLastError to true. Does your function really call SetLastError?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top