当传递给Swift时,Objective-C会释放C ++对象。我该如何预防?

时间:2018-12-03 16:36:28

标签: c++ objective-c swift

我有一个C ++库,需要将其集成到Swift中。我以为那是可行的,直到我意识到我的Objective-C包装器中的C ++对象已被释放。

C ++层

MyCPPClass.hpp

class MyCPPClass {
    std:string myString;
    int myInt;
}

MyCPPProcessor.hpp

class MyCPPProcessor {
    public:
        static MyCPPClass getMeACPPClass();
}

MyCPPProcessor.cpp

MyCPPClass MyCPPProcessor::getMeACPPClass() {
   CPPClass myCPP;
   myCPP.myString = "This is my String";
   myInt = 23;  
   return myCPP;
}

Objective-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的指针,因为它已被释放。

如何防止此版本发布?

1 个答案:

答案 0 :(得分:3)

这与将对象传递给Swift没有任何关系。

问题出在您的+getMeACPPClass方法中。变量myCPPClass具有自动存储功能。它位于堆栈上。当该方法返回时,其堆栈空间无效,并且该对象被销毁。您的Objective-C CPPClassWrapper类仅包含指向同一存储的指针。 C ++对象销毁后,该指针将悬空。

因此,您的点(1)是该变量有效时的 last 点。控件一返回到该方法的调用者,它将立即失效。

您需要执行以下任一操作:1)在std::shared_ptr+getMeACPPClass中在堆上分配对象并使用CPPClassWrapper进行管理;或2)让CPPClassWrapper容纳一个对象,而不仅仅是一个指针,并且它将拥有最初在+getMeACPPClass中创建的对象的副本