Ser*_*uei 12 .net c# interop marshalling
我有这个C++代码:
extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo)
{
*foo = new MY_DATA_STRUCTURE;
//do stuff to foo
}
Run Code Online (Sandbox Code Playgroud)
然后在C#中我调用函数:
[DllImport("MyDll.dll")]
static extern void AllocateFoo(out IntPtr pMyDataStruct);
...
MyDataStructure GetMyDataStructure()
{
IntPtr pData;
ManagedAllocateFooDelegate(out pData);
MyDataStructure foo = (MyDataStructure)Marshal.PtrToStructure(pData, typeof(MyDataStructure));
return foo;
}
Run Code Online (Sandbox Code Playgroud)
MyDataStructure是一个结构(非类),对应于MY_DATA_STRUCTURE,并且成员被适当地编组.
所以问题:当MyDataStructure是GC时,我是否需要存储pData然后在非托管代码中再次发布它?MSDN对Marshal.PtrToStructure(IntPtr,Type)说:"将数据从非托管内存块编组到指定类型的新分配托管对象." 在那句话中,"马歇尔"是指"复制"吗?在这种情况下,我需要保留(IntPtr pData),然后将其传递给非托管代码(在MyDataStructure析构函数中),这样我可以做一个C++"删除"?
我已经搜索过,但我找不到足够明确的答案.
GBe*_*gen 11
正如Erik所说,元帅确实意味着复制,但我不认为他回答了你问题的要点.
你需要保持pData本机指针,直到MyDataStructure被GCed?没有.
封送后,MyDataStructure实例foo包含pData指向的结构的副本.你不需要再持有pData了.为了避免内存泄漏,您必须将该pData传递给另一个将删除它的非托管函数,并且可以在编组后立即完成,无论您保留MyDataStructure实例多长时间.
是的,在这种情况下,马歇尔意味着复制; 因此,您需要在非托管代码中释放内存.对PtrToStructure执行的所有调用都是从pData指向的内存位置读取目标结构"MyDataStructure"大小所指示的字节数.
当然,细节取决于'MyDataStructure'的确切含义(您在MyDataStructure中使用任何FieldOffset或StructLayout属性) - 但最终结果是PtrToStructure的返回是数据的副本.
正如GBegen在答案中指出的那样,我没有回答你问题的要点.是的,您需要在非托管代码中删除结构的非托管副本,但不需要保留pData - 您可以在调用PtrToStructure完成后立即删除非托管副本.
PS:我编辑了我的帖子以包含这些信息,以便将答案合并到一个帖子中 - 如果有人赞成这个答案,请upvote GBegen的回答以及他的贡献.
| 归档时间: |
|
| 查看次数: |
4638 次 |
| 最近记录: |