Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

cpsmusic

macrumors newbie
Original poster
Feb 24, 2008
23
0
Hi,

I'm currently helping out with an open-source cross-platform C++ graphics application. Is it possible to use OS X Cocoa APIs with C++? For example, I'd like to use Image I/O to read and write image formats but I need to call it from within C++.

Cheers,

Chris
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
There are a few problems here. For starters, the cross-platform piece. Once you start using APIs that are OS X-only, it's not cross-platform. Secondly, once you add a single message pass to a C++ file, you have to make it an Objective-C++ file (.mm), so it will compile properly. This means it's Objectve-C(++) now, not C++. It sounds like you are a new contributor to a project with good intentions, but what you're suggesting is totally changing the architecture of the project. I would say call a C function that has some #ifdef code to determine the platform, which calls a C function in your Objective-C library, which can then go to town calling Objective-C methods. This would allow for different per-platform implementations of this behavior. However, it would probably really be best to just use a C or C++ library instead.

-Lee
 

cpsmusic

macrumors newbie
Original poster
Feb 24, 2008
23
0
There are a few problems here. For starters, the cross-platform piece. Once you start using APIs that are OS X-only, it's not cross-platform. Secondly, once you add a single message pass to a C++ file, you have to make it an Objective-C++ file (.mm), so it will compile properly. This means it's Objectve-C(++) now, not C++. It sounds like you are a new contributor to a project with good intentions, but what you're suggesting is totally changing the architecture of the project. I would say call a C function that has some #ifdef code to determine the platform, which calls a C function in your Objective-C library, which can then go to town calling Objective-C methods. This would allow for different per-platform implementations of this behavior. However, it would probably really be best to just use a C or C++ library instead.

-Lee

Thanks for the reply.

My initial thought was to go with a cross-platform library (like you suggest). However, the app already has different capabilities on different platforms (for example, it's using Qt's Phonon for audio I/O which has different capabilities depending on the platform). Also, developers are adding features for particular platforms but not others.

Cheers,

Chris
 

Sander

macrumors 6502a
Apr 24, 2008
521
67
To minimize dependencies, the normal way of doing things like this is to break them out into platform-specific implementations returned from a class factory. So you'd have something like this:

Code:
// Generic code
void GenericClass::LoadImage(const GenericPath& path)
{
    GenericFileIOInterface* itf = CreateSpecificLoader();
    itf->LoadFile(path);
}

The GenericFileIOInterface is a C++ interface, and the CreateSpecificLoader creates a platform-specific implementation. On the Mac, you create an Objective-C++ class in that factory. You select which version to build in the Makefile. That way, the other platforms will never see the .mm file.

If the current cross-platformness is achieved with preprocessor tricks, you'll have to refactor a bit:

Code:
// Generic code
void GenericClass::LoadImage(const GenericPath& path)
{
#ifdef WIN32
    SomeWin32APIForLoadingFilesEx(ConvertPathToLPSZWSTR(path));
#else if LINUX
    some_library_call_for_reading_images(path_to_str(path));
#else
    #error Unknown platform
#endif
}

because, like lee1210 explained, to use Objective-C inside a new #if MACOSX section, the entire file will have to become Objective-C++ which will likely mess it up for the other platforms.
 

NickK1066

macrumors regular
Jul 23, 2007
147
0
Code:
// Generic code
void GenericClass::LoadImage(const GenericPath& path)
{
#ifdef WIN32
    SomeWin32APIForLoadingFilesEx(ConvertPathToLPSZWSTR(path));
#else if LINUX
    some_library_call_for_reading_images(path_to_str(path));
#else
    #error Unknown platform
#endif
}

Eww.. sorry but #defs like this really gets my goat.

Use a mechanism to provide specialist implementations for a cross platform interface. Done correctly there should be little repetition but as others have said it would require refactoring.
 

Sander

macrumors 6502a
Apr 24, 2008
521
67
That's what I meant. Usually, cross-platform compatibility starts out with #ifdefs here and there (especially if it wasn't designed in from the start). If the current state of the code is like that, he'll need to refactor.
 

mfram

Contributor
Jan 23, 2010
1,311
353
San Diego, CA USA
You don't necessarily need #ifdefs. Create different classes that have the same interface to the rest of your program. Compile the one that's appropriate for your project. No #ifdefs will be needed.

graphics_lib_mac.mm
graphics_lib_linux.cpp
graphics_lib_win.cpp

or whatever.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.