我将部分FBX SDK(使用公共API关闭)包含Mono(因此COM,CLI不是选项)和一堆extern' s顺利,直到我必须返回一个非指针实例。 See here
关键是我必须将它返回到C ++以进行另一次调用。因为我不知道你如何在没有指针的情况下做到这一点,我就这样回复了:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
return &obj->GetFirstProperty();
}
..并且直到我尝试下一个代码片段,我得到了" System.AccessViolationException:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。" 消息。
FBXAPI const wchar_t* Property_GetName(FbxProperty* prop)
{
int c = prop->GetSrcPropertyCount();
return L"Test";
}
如果我在C ++中使用相同的调用使用几乎相同的代码,那很好。我以相同的方式完成了另外~20个函数调用,但没有" pointerfy"它,它们一切都很好,所以我不认为我的DllImport应该受到责备。因此,如果引用是责任,我该怎么做呢?当然,我之所以不在某处存储全局静态引用,只是因为有人从API中调用它?
感谢任何帮助,C / C ++和它处理内存的明确方式对我来说是新的。
答案 0 :(得分:1)
我认为您的程序崩溃了,因为您获取指针的属性不再存在。让我澄清并首先剖析以下内容:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
return &obj->GetFirstProperty();
}
我查找了FBX的文档,FbxObject::GetFirstProperty()
的返回类型为FbxProperty
。请注意,返回值不是任何指针或引用?这意味着你得到一个所谓的“自动变量”,或者在这种情况下是一个“临时的”。这种对象只会持续到你离开范围,在这种情况下是你的包装的Object_GetFirstProperty()
。之后,清理对象并从内存堆栈中删除。 FbxObject::GetFirstProperty()
会为您提供该属性的副本,而不是实际的引用。在内部它可能会有所不同,但你的包装器关注的是属性对象本身,而不是它的内容。
所以你正在做的是当你把它传递给Property_GetName()
时,你得到一个指向一个不再有效的地址的指针。
C ++在对象生存期方面的行为与C#不同。 C#中的一个名为MyObj
的对象可以被认为是像MyObject*
这样的C ++指针类型 - 它就像一个参考值。在C#中,您还有像struct
之类的值类型,它们等同于C ++自动变量。所有自动变量在其生命周期范围被删除时都会被销毁。
要解决问题,您必须做的是直接保存从FbxObject::GetFirstProperty()
获得的对象,而不是指向它的指针。您基本上必须将对象编组到正确的.NET类中,以便它的内容不会丢失。
或者,您可以只分配动态内存并将FbxObject::GetFirstPoperty()
中的对象复制到那里,并返回指向您自己内存的指针。当然,您以后必须手动删除此内存。这是一个简单的例子:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
// Allocate custom memory.
char* myMem = new char[sizeof(FbxProperty)];
// Copy the property's content there.
std::memcpy(myMem, &obj->GetFirstProperty(), sizeof(FbxProperty));
// Return custom memory address.
return reinterpret_cast<FbxProperty*>(myMem);
}
这应该可以解决您的内存损坏问题。但是在C ++中你必须手动释放这个内存,当你完成属性时:
FBXAPI void Property_Free(FbxProperty* prop)
{
// Free previously allocated memory
delete[] prop;
}
但是这种尝试可能会导致其他问题,具体取决于实际FbxProperty
处理其内部数据的方式。你正在创建一个对象的副本,但是如果原始的temporaty / auto-variable在破坏时删除了重要的内存,那么你将获得类似于现在的内存。
如果你真的很机智,你可以为你需要的每个FBX类型编写真正的包装类,并编组整个类类型而不是生成separete C函数,每次你想获得一个值或属性时你必须P / Invoke