C ++ DLL LPCTSTR到C#字符串

时间:2015-12-14 09:01:57

标签: c# c++ dll

我正在尝试从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);
}

1 个答案:

答案 0 :(得分:3)

首先,请确保您在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));
}