如何通过 IntPtr 将 C++ 数组封送到 C#

how to marshal c++ array to c# via IntPtr

本文关键字:数组 C++ 何通过 IntPtr      更新时间:2023-10-16

请考虑以下设置:具有 C++ 库的 C# 应用程序。 C# 元素通过回调从 C++ 填充。 在 C# 端,回调定义如下:

void callbackTester(IntPtr pData, UInt32 length)
{
    int[] data = new int[length];
    Marshal.Copy(pData, data, (int)0, (int)length);
    //using data.. on c#
}

现在,在 C++ 端回调是这样定义的:

typedef void (__stdcall *func)(uint8_t* pdata, uint32_t length);

C++ 使用如下回调:

void onData()
{
    std::vector<uint8_t> dataToCallback;
    // fill in dataToCallback
    _callback(&(dataToCallback[0]), dataToCallback.size());
    // where _callback is a pointer to that c# function
}

我的任务:使用回调从 C# 端的 C++ 端获取数组。

因此,当 C++ 对象调用 onData() 函数时,它会从 C# 调用我的回调。 到目前为止一切顺利。 我已经制作了一个 C++ 测试程序,它使用它,并且我在回调端正确接收数组。 如果我在 C# 测试器上使用它,我会收到废话。

例如:如果我发送 {1, 1} 数组uint8_t,我得到 {1, 1} 用于 C++ 测试器,我在 C# 端得到 {0xfeeeabab, 0xfeeefeee}...显然,uint8_t* C++ 指针和 IntPtr c# 之间的转换并没有像我预期的那样工作。

有什么建议吗?非常感谢。

问题似乎是C++ uint8_t是一个无符号字节,而 C# int是一个有符号的 4 字节整数。所以你有一个简单的类型不匹配。与uint8_t匹配的 C# 类型是 byte

您的回调应该是:

void callbackTester(IntPtr pData, uint length)
{
    byte[] data = new byte[length];
    Marshal.Copy(pData, data, 0, (int)length);
}

检查的一件事是,在 C# 端,您期望每个元素有 int-4 字节("int[] 数据"),但在C++上,您只为每个元素分配 uint8-1 字节。

调整分配或长度使用情况,您可能会遇到访问冲突,这就是您看到魔术字节 [1] 的原因。

[1] http://en.wikipedia.org/wiki/Magic_number_(编程)#Magic_debug_values