Calling Objective-C Code from C++

Discussion in 'Mac Programming' started by cpsmusic, Jun 24, 2010.

  1. cpsmusic macrumors newbie

    Joined:
    Feb 24, 2008
    #1
    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
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    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
     
  3. cpsmusic thread starter macrumors newbie

    Joined:
    Feb 24, 2008
    #3
    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
     
  4. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #4
    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.
     
  5. NickK1066 macrumors regular

    Joined:
    Jul 23, 2007
    #5
    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.
     
  6. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #6
    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.
     
  7. mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #7
    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.
     

Share This Page