将vector <dlib :: point>转换为NSArray,以便可以将其传递给Swift类

时间:2018-08-14 11:53:14

标签: c++ objective-c nsarray

我正在使用dlib的面部界标检测器,并希望将面部界标坐标存储在可在Swift中使用的数组中。

目前,我已将地标坐标存储在矢量中:

std::vector<dlib::point> facialLandmarks;

for (unsigned long k = 0; k < shape.num_parts(); k++) {
            dlib::point p = shape.part(k);

            facialLandmarks.push_back(p);
        }

我现在想编写一个将向量转换为NSArray的函数,以便我可以返回该数组并在我的Swift代码中使用它。

当我尝试如下操作时:

 NSArray* facialLandmarksArray = &facialLandmarks[0];

我得到一个错误:

Cannot initialize a variable of type 'NSArray *__strong' with an rvalue of type 'std::__1::__vector_base<dlib::vector<long, 2>, std::__1::allocator<dlib::vector<long, 2> > >::value_type *' (aka 'dlib::vector<long, 2> *')

我对Objective-C或C ++的了解很少,但是需要将其用于Dlib。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

NSArray只能包含 Objective-C 对象,不能包含 C ++ 对象。因此,您必须先将点转换为NSValue。这样的事情应该起作用:

NSMutableArray* facialLandmarksArray = [NSMutableArray arrayWithCapacity: facialLandmarks.size()];

for (auto const& pt: facialLandmarks) {
    [facialLandmarksArray addObject: [NSValue valueWithCGPoint:CGPointMake(pt.x, pt.y)]];
}

并确保将其编译为 Objective-C ++ (文件结尾为* .mm)。

但是,请注意,这对于大向量来说无法很好地缩放。 Swift C ++ 都能够确保通过 Objective-C桥接此类数组/矢量的值存储在consecutive memory中。 em>摧毁了这个地方。

答案 1 :(得分:0)

这里有两个挑战:

1)我们希望最小化界标点的复制,因为这种复制会影响软件性能和内存占用。

2)我们如何在Swift代码中使用C ++ vector的成员,在这种情况下为dlib::point类型的实例?

解决这些挑战取决于用例。需要考虑的一些问题:

1)性能/内存占用量有多重要?如果这不是问题,则可以在将值提供给Swift时复制值。当然,这还取决于C ++代码是否必须使用Swift更改的值。

2)我们在谈论多少个里程碑?如果是100点左右,那么复制它们不太可能会影响性能。

3)Swift代码只是使用C ++库返回的界标点的值吗?还是要修改这些值并期望C ++代码“看到”这些更改?

4)Swift代码通常将访问每个界标点多少次?如果每个点都被访问过多次,那么最好将所有点一次复制到一个可在Swift中使用的结构中,而不用在每次访问中创建一个副本,而不是在每次Swift访问它时都复制一个坐标。

5)可以容忍多少复杂性?您愿意编写很多C ++代码吗?您是否习惯在Swift中使用指针类型,例如UnsafeMutablePointer

以下是有关如何执行此操作的一些想法:

1)在Objective-C ++中构造一个可在Swift中使用的集合,并将界标点坐标值复制到该结构中。 @Tobi的答案就是一个例子。

2)与上面的(1)类似,但是Swift可访问的集合包含指向坐标值的指针。

3)编写一个Objective-C ++类,该类的接口可以从Swift进行访问,并且所有C ++特定的代码都隐藏在实现中。该接口可以允许Swift代码读取(和写入,如果需要)特定界标点的特定坐标。

4)(3)的变体,其中Swift代码访问指向坐标值的指针。在Swift端使用这些控件时,需要格外小心,以免复制坐标值。

如果您提供有关用例的一些细节,我可以尝试举一个例子。