EXC_BAD_ACCESS Xcode,来自我的 Objective-C++ 和 swift 桥接标头中的 C++ 包

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

本文关键字:桥接 swift C++ Objective-C++ Xcode ACCESS BAD 我的 自我 EXC      更新时间:2023-10-16

我正在使用openCV和C++中创建的实用程序类"Detector"开发应用程序。我想为 c++ 类创建一个 objective-c++ 包装器"DetectorWrapper",并在 Swift 中使用此包装器(桥接标头)。但是要知道,当我尝试从 DetectorWrapper 调用 fonction 时,我的应用程序崩溃并显示错误: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++对象被当作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中做一些魔术才能在 2 种类型之间进行转换,但我认为这本身就是一个主题。 顺便说一句,我假设在您的示例中Detector.h并且Detector.hpp引用同一个文件,这只是一个错字。