Reputation: 263
I have been struggling for a day now to get this work. It works well on windows but not on Linux with mono.
C# wrapper
[DllImport("MyLib.dll", CharSet = CharSet.Unicode)]
public static extern int MyFunction(StringBuilder str);
StringBuilder myString = new StringBuilder(255);
var ret = MyFunction(myString);
Console.WriteLine("Result: {0}",myString.ToString());
C++ shared lib (.dll or .so)
WRAPPER_API int _stdcall MyFunction(wchar_t* str)
{
wcscpy(str,L"this is a test");
return 0;
}
Windows:
Result: this is a test
Linux:
Result: t
On mono the returned string contains only the first character of the string. I tried with ANSI string changing wchar_t* to char* and wcscpy to strcpy and it works.
Linux Ubuntu 32 bits 12.04 LTS / Mono 4.3.2
Windows 7 64 bits .Net 4.5
How do I marshal wchar_t* from C++ to C# as an out parameter or return value?
http://www.mono-project.com/docs/advanced/pinvoke/#passing-caller-modifiable-strings
Edit: Thanks to @Xanatos's answer I was able to solve my issue by using u16string (I have g++ 4.8.4 and enable c++11 standard):
WRAPPER_API int _stdcall MyFunction(chart16_t* str)
{
u16string someString(u"some unicode string");
someString.copy(str, someString.length());
return 0;
}
Upvotes: 3
Views: 1476
Reputation: 111940
There is a problem with wchar_t
in Linux: sizeof(wchar_t) == 4
(while on Windows sizeof(wchar_t) == 2
). Sadly Mono on Linux/other Unix(es) doesn't do anything to solve it, and consider sizeof(wchar_t) == 2
everywhere (see for example http://mono-list.ximian.narkive.com/QzgsoSlk/support-for-marshalling-of-c-string-to-unmanaged-wchar-t-on-linux and http://mono.1490590.n4.nabble.com/What-is-Correct-way-to-marshal-wchar-t-td1506090.html .)
There is no simple solution for this. If you are using newer C++ you can use char16_t
with its functions std::char_traits<char16_t>::*
.
Upvotes: 3