EXC_BAD_ACCESS Xcode 来自我的 objective-c++ 和 swift 桥接头文件中的 c++ 包装器

EXC_BAD_ACCESS Xcode from my c++ wrapper in objective-c++ and swift bridging header

我正在使用 openCV 和用 C++ 创建的实用程序 class "Detector" 开发应用程序。我想为 c++ class 创建一个 objective-c++ 包装器 "DetectorWrapper" 并在 Swift (桥接头)中使用这个包装器。但是知道当我尝试从 DetectorWrapper 调用函数时,我的应用程序崩溃并出现错误:EXC_BAD_ACCESS

我在某处读到允许在 Swift 中使用 objective-c++ class,我不能在 DetectorWrapper.h 中包含 c++ 文件,所以我使用类型 id.

这是我的 C++ class:"Detector.h"

#include "opencv2/opencv.hpp"
class Detector
{
public:

    // Constructor
    Detector(int inputPlayerIdx);

    // Scan the input video frame
    void scanFrame(cv::Mat frame);

    // Tracking API
    bool isTracking();
};

我的包装器:"DetectorWrapper.h"

@interface DetectorWrapper : NSObject
@end

@interface DetectorWrapper ()
@property (nonatomic, readwrite, assign) id bld;

- (id)init: (int) inputPlayerIdx;
- (void)dealloc;
- (void) scanFrame: (UIImage*) frame;
- (bool) isTracking;
@end

"DetectorWrapper.mm"

#import "DetectorWrapper.h"
#import "Detector.hpp"
#import "UIImage+OpenCV.h"
@implementation DetectorWrapper
@synthesize bld = _bld;

- (id)init: (int) inputPlayerIdx {
    self = [super init];
    if (self) {
        _bld = (__bridge id) new Detector(inputPlayerIdx);
    }
    return self;
}

- (void)dealloc {
    //[self->_bld dealloc];
    //[super dealloc];
    //delete _bld;
}
- (void) scanFrame: (UIImage*) frame{
    [self->_bld scanFrame:frame];
}
- (bool) isTracking{
    return [self->_bld isTracking];
}
@end

在 Swift 中使用:

let detector = DetectorWrapper(2)
detector.isTracking()

在桥接头中使用文件 "Detector.h"。

调用 .isTracking 时出现 "EXC_BAD_ACCESS" 错误 我根本不明白这个问题以及如何解决它。 也许我只是在编写 objective-c++ 包装器时犯了一个错误,我不习惯这种语言。有什么想法吗?

这里的一个问题是 C++ 对象被当作 Objective-C 对象使用,并且这些类型的对象不可互换。

为了说明和简单起见,让我们删除 scanFrame 方法。然后 DetectorWrapper.h 变成

@interface DetectorWrapper : NSObject
- (id)init: (int) inputPlayerIdx;
- (void)dealloc;
- (bool) isTracking;
@end

和包装器实现:

@implementation DetectorWrapper
{
    // Instance variable to hold a C++ object pointer
    Detector * ptrDetector;
}

- (id)init: (int) inputPlayerIdx {
    self = [super init];
    if (self) {
        ptrDetector = new Detector(inputPlayerIdx);
    }
    return self;
}

- (void)dealloc {
    // Don't want to leak the C++ Detector instance
    delete ptrDetector;
}

- (bool) isTracking{        
    return ptrDetector->isTracking();
}
@end

请注意,当您重新引入 scanFrame 时,您将无法仅将 UIImage* 传递给 ptrDetector->scanFrame(),这需要 cv::Mat,您我必须在包装器的 scanFrame 中做一些魔术才能在这两种类型之间进行转换,但我认为这本身就是一个主题。顺便说一句,我假设在你的例子中 Detector.hDetector.hpp 指的是同一个文件,这只是一个错字。