我有一个C++库,我需要把它集成到SWIFT中。我认为它一直在工作,直到我意识到我的Objy-C包装器中的C++对象被释放了。
C++层
MyCPPClass.hpp公司
class MyCPPClass {
std:string myString;
int myInt;
}
mycpp处理器.hpp
class MyCPPProcessor {
public:
static MyCPPClass getMeACPPClass();
}
mycpp处理器.cpp
MyCPPClass MyCPPProcessor::getMeACPPClass() {
CPPClass myCPP;
myCPP.myString = "This is my String";
myInt = 23;
return myCPP;
}
目标C层
CPPClassWrapper.h文件
@interface CPPClassWrapper : NSObject
@end
CPPClassWrapper.mm类包装纸
@interface CPPClassWrapper()
@property MyCPPClass *myCPPClass;
@end
@implementation CPPClassWrapper
-(instancetype) initWithMyCPPClass:(MyCPPClass *)myCPPClass
{
self.myCPPClass = myCPPClass;
return self;
}
@end
MyProcessorWrapper.h
@interface MyProcessorWrapper : NSObject
+(MyClassWrapper *) getMeACPPClass;
@end
MyProcessWrapper.mm流程包装器
@implementation MyProcessWrapper
+(MyCPPCLassWrapper *) getMeACPPClass
{
MyCPPClass myCPPClass = MyCPPProcessor::getMeACPPClass()
CPPClassWrapper *cppClassWrapper = [[CPPClassWrapper alloc] initWithMyCPPCLass: & myCPPClass];
(1) return cppClassWrapper;
}
@end
当我们到达第(1)行时,一切如期而至。cppClassWrapper有一个指向myCPPClass的指针,可以对其进行检查和验证。
但是,当它被传递到Swift层cppClassWrapper.myCPPClass时,会被释放并调用其析构函数。
快速层
class MyCPPProcessorBridge: MyCPPProcessorWrapper
{
public static func getMeACPPClass -> MyCPPClassBridge
{
let myCPPWrapper:MyCPPClassWrapper = super.getMeACPPClass()
(2) return MyCPPClassBridge(wrapper: myCPPWrapper)
}
}
当我们到达第(2)行时,myCPPWrapper丢失了指向myCPPClass的指针,因为它已被释放。
如何阻止此释放?
最佳答案
这和把你的东西交给斯威夫特没有关系。
问题出在你的+getMeACPPClass
方法上。变量myCPPClass
具有自动存储。它住在烟囱上。当该方法返回时,其堆栈空间将无效,并且该对象将被销毁。Objective-CCPPClassWrapper
类只保存指向同一存储的指针。在C++对象被销毁后,该指针会悬空。
所以,你的点(1)是变量有效的最后一个点。一旦控件返回到该方法的调用方,它就无效。
您需要:1)在堆上分配对象并使用std::shared_ptr
来管理它,在+getMeACPPClass
和CPPClassWrapper
中都是这样;或者2)让CPPClassWrapper
持有一个对象,而不仅仅是一个指针,它将拥有最初在+getMeACPPClass
中创建的对象的副本。