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

时间:2014-04-08 13:36:37

标签: c# c++ pinvoke marshalling

考虑以下设置:c#application with c ++ library。 c#元素通过回调从c ++填充。在c#side回调定义如下:

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#之间的工作并不像我期望的那样。

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

2 个答案:

答案 0 :(得分:1)

问题似乎是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);
}

答案 1 :(得分:0)

要检查的一件事是,在C#方面,你期望每个元素使用int-4字节(&#34; int [] data&#34;)但是在C ++上你只需要为每个元素分配uint8-1字节。

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

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