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?
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:
LPCSTR
to LPCWSTR
on the native side, orUnmanagedType.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
?