C++ and Obj-C playing in the same yard

Oldtimer
Posts: 834
Joined: 2002.09
Post: #1
I've just started work on my new engine, and hit a brick wall right away. Since I intend this to be cross-platform, and I have a pack of nice friends that will write the Windows backend, I need the crossplatform part to be as clean as possible.

Skipping all the boring stuff, it boils down to this:
I'm writing a Cocoa backend for a cross-platform C++ library. The C++ file needs to compile on all platforms as-is, so it can't be a .mm file. Instead, I've written some glue code in C (in a .m file), which I intended to call from the C++ code. This C glue then just calls along to the Cocoa code.

Now, this doesn't work. I get linking errors to the effect that the C++ file can't see the glue symbols. Are C functions in an .m file (containing Obj-C code) mangled in a different way from "pure" C?

Also, is there a better way to bring together C++ and Obj-C? In the long run, having this C glue layer just makes everything so exceedingly complex.
Quote this message in a reply
Moderator
Posts: 435
Joined: 2002.09
Post: #2
I did something similar for my game Asteroid Rally. I think you can't get around needing some glue code but I did mine in C++.

The trick was simply to create a C++ wrapper object, an "envelope" that holds a pointer to the Obj C++ object. The wrapper's header file forward-declares the Obj-C++ object and has an instance variable which is a pointer to it.

Code:
/*
*  Wrapper.h
*/

class WrappedObjCPP;  // forward-declaration of an Obj-C++ class

class GameEvent
{
private:
    WrappedObjCPP *pObj;

public:
[...]

Thanks to the forward declaration, pure C++ files can include Wrapper.h and still compile. Wrapper.mm includes WrappedObjCPP.h and thus hides the Objective-C details from the rest of your program.

Wrappers sure are annoying but I wanted to keep my Obj-C++ "services" isolated from the code of the game which was written in C++. It was a largely theoretical exercise for me because I knew I probably wouldn't ever port that game to Windows. I wrapped game events, sounds, user preferences, and saving high scores, and probably some other things I'm not remembering.

Measure twice, cut once, curse three or four times.
Quote this message in a reply
Member
Posts: 198
Joined: 2005.01
Post: #3
You might need this sort of thing:

#ifdef __cplusplus
extern "C" {
#endif

... C function prototypes ...

#ifdef __cplusplus
}
#endif

I'm using the C intermediate glue layer, it seems to work alright. I have a .mm as well, but I found that the overly picky semantics of C++ causes some issues sometimes. YMMV Smile

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #4
extern "C" did it for me, thanks Dan!
Quote this message in a reply
Member
Posts: 129
Joined: 2005.02
Post: #5
Why don't you just abstract all of your platform specific calls in a platform.h class. Then Mac OS X can be macosx_platform.mm and windows can be win32_platform.mm and etc. That file can house all of your window routines / preference routines / etc.
Quote this message in a reply
Member
Posts: 198
Joined: 2005.01
Post: #6
Fenris Wrote:extern "C" did it for me, thanks Dan!

No problem. FYI in case you're wondering what the heck that does, it tells C++ not to assume name mangling for the enclosed symbols. So void foo() will just become _foo in the link file instead of "vfb_foo$v" or whatever.

Name mangling is one of the great joys of C++. Wink I mean that somewhat pejoratively. It does give you argument overloading and some better link errors, but it's one of the reasons that practically every version of even the same compiler isn't binary compatible.

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Quote this message in a reply
Post Reply