Fire up Cocoa GUI from C++ loop and also passing references

740 Views Asked by At

I have a problem... maybe a couple :)

My team has written a client in C++ using Boost and CMake to take care of the platform dependent stuff. Works like a charm! ...sometimes :) Anyway the graphical interface for Windows is done but for Mac OS X it isn't. Which is also my assignment. Naturally I'm using Cocoa but the problem is that the main loop is in the C++ code and also the GUI should update a few animations depending on the client.

How is this done? I'm very confused about how to nail the threading and how to pass references from the C++ code to the GUI code. Right now the GUI code has its own little MVC totally separated form the rest of the project. I have looked around a lot, maybe I'm too much of a noob :), but I don't fine anything I can really use... I don't really understand it all.

I have tired to recreate the NSApplication. I found this helpful tutorial: http://cocoawithlove.com/2009/01/demystifying-nsapplication-by.html

I have looked a little at Delegates:
How does a delegate work in objective-C?

I have looked a little at NSNotificationCenter:
How to create a class to send and receive events through NSNotificationCenter in Objective-C?


Maybe someone here knows how to make me understand? What to look into? Where I should look?

1

There are 1 best solutions below

2
On

Your question is rather general so I can only give some high level architectural tips for a predominantly C++ based application that you want to port to Mac OS X and have a native Cocoa UI.

Threads: Just because the C++ code has the main thread on Windows does not mean that it needs to be on Mac OS X. Start your application the usual Cocoa way with NSApplication and then in your app delegate's applicationDidFinishLaunching you should do two things:

  1. Launch an NSThread even if it does nothing and just returns immediately. You need to do this to switch Cocoa to be internally thread safe (such as it can be). Since your C++ code will instead be launching pthreads you need to start at least one higher level NSThread first.
  2. Call into the startup routines of your C++ code. If this code is long running, launch a separate thread. There is no reason why the your C++ code needs to be running on the main thread on Mac OS X; it can be on any auxiliary thread. The only special thing about the main thread on Mac OS X is that events are delivered there and UI changes should take place from there. Both of these things should be handled in Cocoa native code, not in portable C++ code.

Language Barrier You have a language barrier to deal with. Your C++ code can't directly access Objective-C objects and visa versa. You can smooth over this problem with Objective-C++ but best practice is to use Objective-C++ only for a thin translation layer and keep the two separate. In addition to providing a more canonical programming environment it also helps logically to separate UI code (in Objective-C) from lower level application services (in C++). Rob Napier has written a lot about how to do this and I suggest reading his recent blog post along with some of his earlier posts on the subject.

To elaborate a bit more generally you will be using one of several techniques to go from C++ to Objective-C since that is the direction you asked about:

  1. Provide C interface functions that can be called from Objective-C or C++. Their implementation can be written in whatever language is most convenient. The header for these functions will have lines like the following to let the C++ code know they have C and not C++ interfaces:

    #if defined __cplusplus
    extern "C" {
    #endif
    void passAString(const char *string);
    // ... some other C interface functions
    #if defined __cplusplus
    }
    #endif
    
  2. Provide Objective-C++ bridge functions that take C++ objects and translated them to Objective-C objects before calling the native Objective-C code.

  3. Write Objective-C++ bridge objects. These provide a thin C++ veneer to an underlying Objective-C object so the C++ layer can interact with it.

Obviously you will need to use similar techniques in the reverse to call from Objective-C code to C++.