首页 > 解决方案 > EXC_BAD_ACCESS Xcode 来自我在 Objective-C++ 中的 C++ 包装器和 Swift 桥接头

问题描述

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

我在哪里读到允许在 Swift 中使用 Objective-C++ 类,我不能在 DetectorWrapper.h 中包含 C++ 文件,所以我使用类型 ID。

这是我的 C++ 类:“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++swiftobjective-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引用同一个文件,这只是一个错字。


推荐阅读