C ++ DLL LPCTSTR到C#字符串
我试图从C ++ DLL到C#获取字符串。 它输出不正确的符号 – {栠搂珯获긋ݳݳ赠琹玴ɡݳݳ}
这是我的代码:C ++ DLL
_declspec(dllexport) int __stdcall myClass(LPCTSTR& z) { z = _T("Test String"); return 0; }
我的C#代码读取C ++ DLL:
[DllImport("ecrClassDll.dll", CharSet = CharSet.Unicode)] static extern void myClass(StringBuilder z); static void Main(string[] args) { StringBuilder z = new StringBuilder(); myClass(z); }
首先,确保在C ++中定义了UNICODE
宏,以便_T
输出wchar_t
数据, LPCTSTR
表示const wchar_t*
。 这就是CharSet.Unicode
期望的。 顺便说一句,如果你不打算支持ANSI版本,我也不会打扰所有这些_T
东西,只是到处使用Unicode,代码会更简单。
此外,您的C ++函数返回一个int
,但您的C#函数需要一个void
。 你有不匹配(除非你打算将PreserveSig
设置为false
)。
在C#方面,当你提供一个StringBuilder
,它意味着你向C ++端提供一个缓冲区,你希望它填充该缓冲区。 正确的用法是这样的:
_declspec(dllexport) int __stdcall myClass(LPCTSTR z, int zSize) { _tcscpy_s(z, zSize, _T("Test String")); return 0; }
[DllImport("ecrClassDll.dll", CharSet = CharSet.Unicode)] static extern int myClass(StringBuilder z, int zSize); static void Main(string[] args) { StringBuilder z = new StringBuilder(256); myClass(z, z.Capacity); }
但是你的代码返回一个指向静态字符串的指针,这是marshaller在这里不期望的。
如果你想保持你的C ++代码,你可以尝试这样做:
[DllImport("ecrClassDll.dll", CharSet = CharSet.Unicode)] static extern int myClass(out string z); static void Main(string[] args) { string z; myClass(out z); }
我承认我没有测试它,但它应该工作,因为这个C#签名匹配C ++签名。
如果一切都失败了,您可以尝试自己编组数据:
[DllImport("ecrClassDll.dll")] static extern unsafe int myClass(void** z); static unsafe void Main(string[] args) { void* z; myClass(&z); var str = Marshal.PtrToStringUni(new IntPtr(z)); }