Search code examples
c++objective-cnsarray

Convert a vector<dlib::point> to an NSArray so it can be passed to a Swift class


I'm using dlib's facial landmark detector and want to store the facial landmark coordinates in an array that can be used in Swift.

At the minute I've stored the landmark coordinates in a vector:

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);
        }

I now want to write a function that will convert the vector into an NSArray so that I can return the array and use it within my Swift code.

When I try things like the following:

 NSArray* facialLandmarksArray = &facialLandmarks[0];

I get an error:

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> *')

I really know very little about Objective-C or C++ but need to use it for Dlib. Any help would be really appreciated!


Solution

  • NSArrays can only contain Objective-C objects, no C++ objects. So you have to convert your points to NSValues first. Something like this should work:

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

    And make sure this is compiled as Objective-C++ (file ending *.mm).

    However, note that this does not scale well for large vectors. Swift and C++ are both able to make sure that the values of such arrays/vectors are stored in consecutive memory, bridging through Objective-C destroys this locality.