Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

easing c++ to objective-c/cocoa bridging via metaprogramming?

In a pure C++ world we can generate interfacing or glue code between different components or interfaces at compile time, using a combination of template-based compile-time and runtime-techniques (to e.g. mostly automatically marshall to/from calls using legacy types).

When having to interface C++ applications with Objective-C/Cocoa for GUI, system integration or IPC though, things become harder due to the less strict typing - yet often not more then a flat repitive interface layer is needed: thin bridging delegates have to be defined or conversion code to language bridging calls has to be written.

If you have to deal with interfaces of non-trivial size and want to avoid script-based code generation this quickly becomes cumbersome and is just a pain every time refactorings have to take place. Using a combination of (template) metaprogramming and the Objective-C runtime library, it should be possible to reduce the amount of code considerably...

Before i go to reinvent the wheel (and possibly waste time), does anyone know about techniques, best-practices or examples in that direction?


As for an example, lets say we need a delegate that supports this informal protocol:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2; - (NSNumber*)     indexOf:(CustomClass*)obj; 

Instead of implementing an Obj-C class now that explicitly bridges to a C++-instance, i'd like to do something like this instead:

class CppObj {     ObjcDelegate m_del; public:     CppObj() : m_del(this)      {         m_del.addHandler             <NSString* (NSString*, NSString*)>             ("concatString", &CppObj::concat);         m_del.addHandler             <NSNumber* (CustomClass*)>             ("indexOf", &CppObj::indexOf);     }      std::string concat(const std::string& s1, const std::string& s2) {         return s1.append(s2);     }      size_t indexOf(const ConvertedCustomClass& obj) {         return 42;     } }; 

All that should be needed from the user to support additional types would be to specialize a conversion template function:

template<class To, class From> To convert(const From&);  template<>  NSString* convert<NSString*, std::string>(const std::string& s) {      // ... }  // ... 

The example above of course does ignore support for formal protocols etc. but should get the point across. Also, due to the type-information for Objc-runtime-types being mostly decayed into some-native-types or class-type i don't think the explicit specification of parameter and return types for the delegate-methods can be avoided.

like image 904
Georg Fritzsche Avatar asked Feb 16 '10 22:02

Georg Fritzsche


2 Answers

I didn't find anything satisfactory and came up with a prototype that, given the following informal protocol:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2; 

and this C++ code:

struct CppClass {     std::string concatStrings(const std::string& s1, const std::string& s2) const {         return s1+s2;     } };  std::string concatStrings(const std::string& s1, const std::string& s2) {     return s1+s2; } 

allows creating and passing a delegate:

CppClass cpp; og::ObjcClass objc("MyGlueClass"); objc.add_handler<NSString* (NSString*, NSString*)>     ("concatString:withString:", &cpp, &CppClass::concatStrings); // or using a free function: objc.add_handler<NSString* (NSString*, NSString*)>     ("concatString:withString:", &concatStrings); [someInstance setDelegate:objc.get_instance()]; 

which can then be used:

NSString* result = [delegate concatString:@"abc" withString:@"def"]; assert([result compare:@"abcdef"] == NSOrderedSame); 

Boost.Function objects can also be passed, which means Boost.Bind can easily be used as well.

While the basic idea works, this is still a prototype. I did a short blog post on the subject and the prototype source is available via bitbucket. Constructive input and ideas welcome.

like image 113
3 revs Avatar answered Sep 20 '22 20:09

3 revs


Did you look at the wxWidgets library? I don't code in Objective-C, but at least the developers claim decent support for Cocoa/Objective-C. Which means, they have some mapping from C++ implemented somehow. The library's website is http://www.wxwidgets.org.

like image 34
Kerido Avatar answered Sep 21 '22 20:09

Kerido