我有一个Objective-C类,它用数百万个点填充std:vector
。向量的结构为:
typedef std::vector<CGPoint> CGContour;
typedef std::vector<CGContour> CGContours;
因此,
CGContour
是CGPoints的向量,而CGContours
是CGContour
向量的向量。我需要以某种方式在Swift类中访问此数据。我不想使用NSArray,因为与使用向量相比,它具有巨大的开销(它的大小和速度都快10倍)。
从我的Objective-C类中获取Swift中数百万个CGPoint的最有效方法是什么?
编辑:
我正在这样填充
CGContours
向量:contourVector = CGContours(contours.size());
populatedContourNum = 0
//contours is OpenCV's contours
for( long c = 0; c < contours.size(); c++) {
if (populatedContourNum >= contourVector.size()) {
contourVector.resize(contourVector.size() + 1);
}
contourVector[populatedContourNum] = CGContour(contours[c].size());
for( long pointNum = 0; pointNum < contours[c].size(); pointNum++ )
{
contourVector[populatedContourNum][pointNum] = CGPointMake(contours[c][pointNum].x * scale,
contours[c][pointNum].y * scale);
}
populatedContourNum++;
}
最佳答案
有些部分不够清晰,但我将尝试向您展示一些示例。
首先,您需要准备一个可以访问您的contourVector
的类。 (我看不到它是实例字段还是全局变量,如果它是实例字段,则可以使用现有的类。)
为准备好的类创建一个头,再次使用现有的头,但是此头需要在C上下文和C ++上下文中进行编译。因此,如果您现有的标头包含一些不能在C上下文中编译的声明,则可能需要分隔两个标头或某些#if
。
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface YourClass : NSObject
- (NSInteger)contoursSize;
- (NSInteger)contourSizeAtIndex:(NSInteger)index;
- (CGPoint *)contourAtIndex:(NSInteger)index;
//...
@end
NS_ASSUME_NONNULL_END
然后将3个方法添加到标头中指定的类中:
#import "YourClass.h"
#import <vector>
typedef std::vector<CGPoint> CGContour;
typedef std::vector<CGContour> CGContours;
static CGContours contourVector;
@implementation YourClass
- (NSInteger)contoursSize {
return contourVector.size();
}
- (NSInteger)contourSizeAtIndex:(NSInteger)index {
return contourVector[index].size();
}
- (CGPoint *)contourAtIndex:(NSInteger)index {
return contourVector[index].data();
}
@end
请不要忘记在
Project-Bridging-Header.h
中包含标题://
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "YourClass.h"
您需要创建一个Swift侧包装类,因为您不能在Objective-C中创建
UnsafeBufferPointer
。class YourClassWrapper {
let yourInstance = YourClass()
var count: Int {
return yourInstance.contoursSize()
}
subscript(index: Int) -> UnsafeBufferPointer<CGPoint> {
guard 0..<count ~= index else {fatalError("Index \(index) out of bounds \(0..<count)")}
let start = yourInstance.contour(at: index)
let count = yourInstance.contourSize(at: index)
return UnsafeBufferPointer(start: start, count: count)
}
}
通过上面的这些准备,您可以按以下方式访问每个
CGPoint
:let wrapper = YourClassWrapper()
let point = wrapper[0][1]
或者,您可以通过以下方式获取指向
CGContour
中第一个元素的指针:let ptr = wrapper[0].baseAddress!
您可能需要修改某些部分以使其适合您的实际代码。希望你能做到。