如何通过p / invoke将c#字符串传递给linux / glibc wchar_t *参数?

问题描述 投票:0回答:2

我有一个.NET Core 2.2 C#应用程序,它使用DllImport在CentOS 7.5上引入本机共享库(用gcc编译的C ++ extern“C”接口)。 C ++库中的函数需要wchar_t *参数,但这些参数似乎被编组为UTF16字符串而不是gcc / glibc中实现的UTF32字符串。是(我的)程序员错误还是应该与.NET Core团队一起提出?

这是我试图调用的非常复杂的方法:

void wchar_tTest(const wchar_t *arg1, const wchar_t *arg2)
{
    std::wcout << L"wchar_tTest: arg1: " << arg1 << L", arg2: " << arg2 << std::endl;

    char *s = (char *)arg1;
    for (int i = 0; i < 12; i++)
    {
        printf("%d: %c\n", i, s[i]);
    }
}

我尝试在管理端的DllImport上使用MarshalAs(UnmanagedType.LPWSTR)和/或CharSet.Unicode无济于事。这些都产生类似的结果:

[DllImport("cover", EntryPoint = "wchar_tTest", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void LPWSTRStringTest([MarshalAs(UnmanagedType.LPWStr)] string arg1, [MarshalAs(UnmanagedType.LPWStr)] string arg2);

[DllImport("cover", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void wchar_tTest(string arg1, string arg2);

调用看起来像这样(stringTest()是一个类似的调用,但是带有char *参数的函数):

string arg1 = "Hello!";
string arg2 = "Goodbye!";

stringTest(arg1, arg2);

wchar_tTest(arg1, arg2);

LPWSTRStringTest(arg1, arg2);

当参数通过wcout被淘汰时,Hello!变成HloGoodbye!变成Gobe。当你逐个字符地输出时,输出看起来像UTF16 ......看起来像wchar_t *跳过其他所有UTF16字符(将其视为我假设的UTF32字符串)。

wchar_tTest: arg1: Hlo, arg2: Gobe
0: H
1: 
2: e
3: 
4: l
5: 
6: l
7: 
8: o
9: 
10: !
11: 

有没有办法在不进行自定义编组的情况下解决这个问题?毕竟我读过它似乎应该是一个简单的任务,但我在这里。

c# linux gcc .net-core pinvoke
2个回答
0
投票

该文本被编组为UTF16,这是按照预期和设计的。你需要:

  • 调整您的C ++代码以在UTF16上运行,或
  • 使用其他编码的自定义编组,例如UTF8或UTF32。

-1
投票

鉴于我所看到的流量没有很好的答案,我将发布我正在使用的短期黑客来解决这个问题,因为世界的C ++ /本地库方面无法改变...

我修改了DllImport以声明byte []参数

[DllImport("cover", EntryPoint = "wchar_tTest", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void utf32Test(byte[] arg1, byte[] arg2);

并创建了.NET字符串的UTF32编码版本

string arg1 = "Hello!";
byte[] arg1UTF32 = Encoding.UTF32.GetBytes(arg1);
string arg2 = "Goodbye!";
byte[] arg2UTF32 = Encoding.UTF32.GetBytes(arg2);

utf32Test(arg1UTF32, arg2UTF32);

并且你得到了预期的输出字符串和数组内容

wchar_tTest: arg1: Hello!, arg2: Goodbye!
0: H
1: 
2: 
3: 
4: e
5: 
6: 
7: 
8: l
9: 
10: 
11: 

这虽然不是很便携,但当你在Windows系统上运行它时当然会失败。我希望有更好的答案。

© www.soinside.com 2019 - 2024. All rights reserved.