我有一个Objective-C类,它用数百万个点填充std:vector。向量的结构为:

typedef std::vector<CGPoint> CGContour;
typedef std::vector<CGContour> CGContours;


因此,CGContour是CGPoints的向量,而CGContoursCGContour向量的向量。

我需要以某种方式在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!




您可能需要修改某些部分以使其适合您的实际代码。希望你能做到。

10-08 04:43