2

I'm writing a wrapper to call some C++ from Swift. I understand that to call a C++ std::vector I should use NSArray, but the following code fails to compile on the last two function arguments with the error

Type argument 'PolylineElement' is neither an Objective-C object nor a block type

struct PolylineElement
{
    int x1;
    int y1;
    int x2;
    int y2;
};

@interface CPPWrapper : NSObject
- (void) grabberInitializeAndProcessFromPixels: (unsigned char*) pbInPixels
                                   andInStride: (int) inStride
                                  andOutPixels: (unsigned char*) pbOutPixels
                                  andOutStride: (int) outStride
                                      andWidth: (int) width
                                     andHeight: (int) height
                             andMarqueeTopLeft: (Point) mqTopLeft
                            andMarqueeTopRight: (Size) mqSize
                            // Next two lines fail
                            andForegroundMarks: (NSArray<PolylineElement> *) pForegroundMarks
                            andBackgroundMarks: (NSArray<PolylineElement> *) pBackgroundMarks
                               andGrabberState: (void *) pGrabberState;
@end

How do I declare an NSArray of a struct?

If, following trojanfoe's advice in the comments I make PolylineElement into a class thus

@interface PolylineElement : NSObject
{
    int x1;
    int y1;
    int x2;
    int y2;
}
@end

then I get the error

Type argument 'PolylineElement' must be a pointer (requires a '*')

But if I fix the function call to use pointers thus

@interface CPPWrapper : NSObject
- (void) grabberInitializeAndProcessFromPixels: (unsigned char*) pbInPixels
                                   andInStride: (int) inStride
                                  andOutPixels: (unsigned char*) pbOutPixels
                                  andOutStride: (int) outStride
                                      andWidth: (int) width
                                     andHeight: (int) height
                             andMarqueeTopLeft: (Point) mqTopLeft
                            andMarqueeTopRight: (Size) mqSize
                            andForegroundMarks: (NSArray<PolylineElement *> *) pForegroundMarks
                            andBackgroundMarks: (NSArray<PolylineElement *> *) pBackgroundMarks
                               andGrabberState: (void *) pGrabberState;
@end

I do not get compiler issues but each element of the array is now a pointer, not what the C++ is expecting, i.e. there is an extra level of indirection.

Community
  • 1
  • 1
dumbledad
  • 16,305
  • 23
  • 120
  • 273
  • You can wrap `struct`s, however it's probably better to create a custom `NSObject`-subclass object. – trojanfoe Nov 05 '15 at 11:39
  • Thanks trojanfoe, I've updated the question to take this suggestion into account – dumbledad Nov 05 '15 at 11:50
  • You'll need to show the code that error is referring to. – trojanfoe Nov 05 '15 at 11:53
  • There's no error now - I just don't understand how a pointer to an object on the Objective-C side will be interpreted as a struct on the C++ side. I.e. how `(NSArray *)` in Objective-C can equate to `(std::vector *)`. I'll push on and formulate another question when there's an actual error to grapple with. – dumbledad Nov 05 '15 at 11:58
  • It's not. If you need it in C++ you'll need to write a function to convert NSArray to std::vector by iterating through it. – personjerry Nov 05 '15 at 11:59
  • Yeah it's not clear exactly what you are doing. I assume it's swift -> Objective-C++ -> C++? I would imagine in that case it's better to use `std::vector` internally within the Objective-C++ class (and don't expose it via the header file) and then to have methods to add/remove elements from the collection. Then just give the `vector` straight to the C++. – trojanfoe Nov 05 '15 at 12:33

0 Answers0