C# 将带有字符串的结构编组到 C 库

C# Marshalling Structure with Strings to C Library

我正在编写一个 C 库,我必须从 Unity3D (C#) 与之交互,并且运行正在编写我的一个 PInvoke 调用时遇到问题。

我有以下 c 结构

typedef struct TestStruct
{
    const char* Method;
    const char* Url;
} TestStruct;

和C函数签名

__declspec(dllexport) void __cdecl TestMethod(TestStruct* args)
{
    // Do stuff with Method and URL
}

在 C# 中,我已经像这样创建了我的结构

[StructLayout(LayoutKind.Sequential)]
public struct TestStruct
{
    public string Method;
    public string Url;
}

像这样的 PInvoke 签名

[DllImport("Test", CallingConvention = CallingConvention.Cdecl)]
private static extern void TestMethod(TestStruct args);

现在,当我在 Win64 的 Unity 编辑器中 运行 它工作正常。但是当我将它部署到我的 android 设备(我认为是 32 位 ARM 架构的 Nexus 6)时,方法和 Url 属性在我的测试结构中到达 C lib 时为 null。

奇怪的是,如果我更改我的函数签名以采用完全避免结构的原始参数,它工作得很好。

__declspec(dllexport) void __cdecl TestMethod(const char* Method, const char* Url)
{
    // Do stuff with Method and URL
}

[DllImport("Test", CallingConvention = CallingConvention.Cdecl)]
private static extern void TestMethod(string method, string url);

工作正常。有谁知道我可能做错了什么吗?

这个:

__declspec(dllexport) void __cdecl TestMethod(TestStruct* args)

相当于:

[DllImport("Test", CallingConvention = CallingConvention.Cdecl)]
private static extern void TestMethod(ref TestStruct args);

out TestStruct,取决于谁将写入 TestStruct

重要提示:如果 string 是通过 C->C# 传递的,则 C# 不应修改它们(否则 .NET 将尝试使用错误的释放器释放它们,并且会发生不好的事情)。如果你使用 out TestStruct,C 端将不得不释放返回的 const char* 我不得不说我不知道​​具体如何(因为你使用的是 Unity 而不是 [=25 下的 .NET =], 所以事情变得有点毛茸茸)