我有一个这个结构的数组数组(在C#中显示,但也存在于C ++中):
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
IntPtr name; //pointer to string, char* on C++ side
long pValues;
long jValues;
long eValues;
long kValues;
int cost;
};
和C ++ DLL中的一个算法,它可以在托管C#代码中调用它。它的CPU很重,这就是必需的,因为它在C ++中的运行速度比C#快得多。托管(C#)方面永远不必知道结构数据的内容,因为算法只返回单个int数组。
那么,在应用程序的生命周期内,我将如何以最有效的方式(即开销最小)存储这些数据?我想我已经把它缩小到两个选项:
初始化C#中的结构和设置值,使用GCHandle设置内存,并在我想要工作时将引用传递给C ++(参见Unity论坛上的this post)
在C ++中初始化结构和设置值,结构在非托管端的内存中保留
所以我的问题非常具体:
1,我对编组的工作方式感到困惑。在MSDN: Copying and Pinning中,您可以通过固定并传递对固定数据的引用来传递结构数组,而无需复制或转换任何(并且只要结构在两边看起来都一样)。我是否正确阅读,它是如何实际工作的?参考Unity3d论坛帖子,我看到Marshal.PtrToStructure正在被调用;我以为会执行复制操作?由于数据将在此实例中存储在托管端,因此每次调用C ++函数时都必须复制和/或转换数据会导致大量开销,除非我认为这些类型的操作是比他们实际上要贵很多。
有了2,我想知道是否可以在C ++调用之间保持持久性。据我所知,如果你从DLL调用P / Invoke,你就不能在非托管端拥有持久数据,所以我不能在那里定义和存储我的struct数组,使得在托管和非托管之间传输的唯一数据是由非托管算法产生的int数组。这是对的吗?
非常感谢你花时间阅读和帮助!
答案 0 :(得分:3)
如果C#代码不需要知道数组的内部结构和结构,请不要将它暴露给C#代码。在非托管代码中完成此类型的所有工作,避免编组开销。
基本上,你想要遵循这个基本模式。我确定细节会有所不同,但这应该为您提供基本概念。
<强> C ++ 强>
MyStruct* newArray(const int len)
{
return new MyStruct[len];
}
void workOnArray(MyStruct* array, const int len)
{
// do stuff with the array
}
void deleteArray(const MyStruct* array)
{
delete[] array;
}
C#
[DllImport(dllname)]
static extern IntPtr newArray(int len);
[DllImport(dllname)]
static extern void workOnArray(IntPtr array int len);
[DllImport(dllname)]
static extern void deleteArray(IntPtr array);