Wrapping objective-c classes into c++ classes: best practices?
Asked Answered
R

2

2

I have a c++ class implemented in a objective-c++ (.mm) file. This class contains some Cocoa object, say a NSToolbar, as a (private) member variable. The class should be exposed as a pure c++ interface and usable by pure c++ clients. In other words, I am trying to wrap obj-c objects in a c++ class.

The first thing that crosses my mind is to use a void pointer in the class interface and then work around with casting within the class implementation, whenever _toolbar needs to be treated as a NSToolbar.

For example I would have the interface:

// NSToolbarWrapper.h
class NSToolbarWrapper {
private:
void * _toolbar;

//... rest of the class ...

}

and the implementation:

// NSToolbarWrapper.mm
...
ToolbarWrapper::ToolbarWrapper (...){
_toolbar = (__bridge void *)[[NSToolbar alloc] initWithIdentifier:@"My toolbar!"];
...
}

I am not sure this is the smartest approach. Is there a best practice in this case?

Rizzio answered 1/10, 2014 at 13:27 Comment(1)
I have found the best approach is to use the pimpl idiom when declaring the class that will be exposed to pure c++Dena
D
4

Pimpl idiom with c++ interface and objective c++ implementation. You'll need to declare your destructor and define it in the .mm file if you use unique_ptr as your pimpl;

class.h:

class myclass {
    class impl;
    std::unique_ptr<impl> _impl; // or shared_ptr if you want shared handle behaviour

public:
    myclass(const char* s);
    ~myclass(); // only declare here
};

class.mm:

class myclass::impl {
    NSString* _str;
public:
    impl(const char* s) 
    : _str([NSString stringWithCString:s encoding: NSASCIIStringEncoding]) 
    {}
};

myclass::myclass(const char* s)
: _impl(new impl(s))
{}

myclass::~myclass() = default;  // define here
Dena answered 1/10, 2014 at 13:42 Comment(0)
R
0

For the sake of documentation, and to remind myself in the future.

I have seen a pretty well-known open source library doing like this, which also seems to be a valid approach:

// NSToolbarWrapper.h
#ifdef __OBJC__
typedef NSToolbar *Toolbar;
#else
typedef class NSToolbar_opaque *Toolbar;
#endif // __OBJC__

class NSToolbarWrapper {
private:
Toolbar _toolbar;

//... rest of the class ...

}
Rizzio answered 6/10, 2014 at 14:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.