将大型std :: vector转换为Swift的最有效方法?

时间:2019-05-22 23:08:14

标签: arrays objective-c swift nsarray stdvector

我有一个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++;

}

1 个答案:

答案 0 :(得分:0)

某些部分不够清晰,但我将尝试向您展示一些示例。

首先,您需要准备一个可以访问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!

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