atm i'm writing code simultaneously for windows, mac, linux, psp and the ti c6xx platforms.
basically i use a global platfrom definition file for general stuff, which contains things like this:
Code: Select all
#ifdef WIN32
#define S_WIN32 1
#elif defined LINUX
#define S_LINUX 1
#elif defined MAC
#define S_MAC 1
#elif defined C6X
#define S_C6X 1
#elif defined DAVINCI
#define S_DAVINCI 1
#elif defined PSP
#define S_PSP 1
#else
#ERROR !no platform defined!
#endif
  #ifdef S_DEBUG
      /**
        * Output debug string.
        * @see Tracer::sf_TraceDebug()
        */ 
    #define DBG( text ) utils::Tracer::sf_TraceDebug( text );
    
      /**
        * Output debug string, printf style.
        * @see Tracer::sf_TraceDebugPrintf()
        */ 
    #define DBGPF( format, args ) utils::Tracer::sf_TraceDebugPrintf( format, args );
      //assert
    #if defined S_WIN32
      #define s_assertf   { __asm int 3 }
    #elif defined S_LINUX
        //ok here's something stupid: when using single stepping
        //using gdb, it will just step over the s_assert and
        //ignore the SIGTRAP raised.
        //It won't ignore it however if running, or if stepping
        //over a function that contains the assert inside.
        //Keep this in mind when debugging!
      #define s_assertf  { asm("int $3"); }
    #elif defined S_MAC
      #define s_assertf  Debugger();
    #elif defined S_C6X
      #define s_assertf { asm("int 3") }
    #elif defined S_PSP
      #define s_assertf { asm("int 3"); }
    #endif
      /**
        * Platform-independent assertion.
        * Gets optimized away in release builds.
        */
    #define s_assert( expr ) { if( !( expr ) ) s_assertf }
  #else
then i write interfaces for all things that are really platform specific: threads, criticalsections, waitable objects, sockets, basic ui stuff... and implement these for every platform.
eg the criticalsection interface looks like this:
Code: Select all
class CriticalSection
  {
  public:
      /**
        * Constructor.
        */
    CriticalSection();
      /**
        * Destructor.
        */
    ~CriticalSection();
      /**
        * Enters the CriticalSection.
        * If another thread has entered before, the method
        * blocks until that thread leaves it again.
        * Else the method returns immedeately.
        */
    void mf_Enter() const;
      /**
        * Trie to enter the CriticalSection.immedeately.
        * If another thread has entered before, the method
        * returns false and doe not enter, else it returns true
        * after entering.
        * @return false if the CriticalSection isn't free
        */
    bool mf_bTryEnter() const;
      /**
        * Leave the CriticalSection.
        * Make sure not to call this on a CriticalSection that
        * has not been entered.
        */
    void mf_Leave() const;
  private:
  #if defined S_WIN32
    char m_hMutex[ 24 ];     //!< aka win32 CriticalSection
  #elif defined S_C6X
    LCK_Handle m_hMutex;
  #elif defined S_LINUX
    mutable pthread_mutex_t m_hMutex;
  #elif defined S_PSP
    SceUID m_hMutex;
  #endif
    CriticalSection (const CriticalSection&);
    const CriticalSection& operator= (const CriticalSection&);
  };
all methods are then implemented in psp_criticalsection.cpp/win32_criticalsection.cpp etc, so while building i just have to include the right file while compiling
the rest of the code uses the interfaces only, so all application code is completely platform independent.
i don't use fancy uis mostly, except on pc maybe and then i use qt which is pretty cross-platform, but opengl should do it too.
it's a *lot* of work, takes an equal lot of testing, but the pc/dsp part i have to code for my job anyway so i have the time..
once the code is there it's a dream to use: i first write it in my favorite ide on pc, test it for mem leaks etc, and when it works, i just use it on the platform i want, and i know it will work there too without surprises
hopefully this is a bit of interest for you, i'm not really allowed to post this code []-]