简体   繁体   English

C ++ DLL LPCTSTR到C#字符串

[英]C++ DLL LPCTSTR to C# string

I am trying to get string from C++ DLL to C#. 我试图从C ++ DLL到C#获取字符串。 It outputs incorrect symbols - {栠搂珯獲긋ݳݳ贈琹玴ɡݳ⻜} 它输出不正确的符号 - {栠搂珯获긋ݳݳ赠琹玴ɡݳݳ}

Here is my code: C++ DLL 这是我的代码:C ++ DLL

_declspec(dllexport) int __stdcall myClass(LPCTSTR& z)
{
    z = _T("Test String");
    return 0;
}

My C# code reading C++ DLL: 我的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);
}

First, make sure you defined the UNICODE macro in C++, so that _T outputs wchar_t data, and LPCTSTR means const wchar_t* . 首先,确保在C ++中定义了UNICODE宏,以便_T输出wchar_t数据, LPCTSTR表示const wchar_t* That's what CharSet.Unicode expects. 这就是CharSet.Unicode期望的。 By the way, if you don't intend to support an ANSI version too, I wouldn't bother with all this _T stuff and just use Unicode everywhere, the code will be simpler. 顺便说一句,如果你不打算也支持ANSI版本,我不会打扰所有这些_T东西,只是到处使用Unicode,代码会更简单。

Also, your C++ function returns an int , but your C# function expects a void . 此外,您的C ++函数返回一个int ,但您的C#函数需要一个void You have a mismatch there (unless you intended to set PreserveSig to false ). 你有不匹配(除非你打算将PreserveSig设置为false )。

On the C# side, when you provide a StringBuilder , it means you provide a buffer to the C++ side, and you expect it to fill that buffer. 在C#方面,当你提供一个StringBuilder ,它意味着你向C ++端提供一个缓冲区,并且你希望它填充该缓冲区。 The correct usage would be something like this: 正确的用法是这样的:

_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);
}

But your code returns a pointer to a static string, which the marshaller doesn't expect here. 但是你的代码返回一个指向静态字符串的指针,这是marshaller在这里不期望的。

If you'd like to keep your C++ code as-is, you could try this instead: 如果你想保持你的C ++代码,你可以尝试这样做:

[DllImport("ecrClassDll.dll", CharSet = CharSet.Unicode)]
static extern int myClass(out string z);

static void Main(string[] args)
{
    string z;
    myClass(out z);
}

I admit I didn't test it, but it should work as this C# signature matches the C++ signature. 我承认我没有测试它,但它应该工作,因为这个C#签名匹配C ++签名。

If everything fails, you could try to marshal the data by yourself: 如果一切都失败了,您可以尝试自己编组数据:

[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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM