Wrapping Libraries / Multiple Platforms

Started by
5 comments, last by swiftcoder 7 years, 4 months ago

Hello forum : )

I was wondering if it is common practice to wrap around classes from external libraries in order to interchange such library by another.

And how modern C++ tackle to provide multiple builds for multiple OS.

What I do:

I have the same files used by multiple projects, one project per OS.

All I do is linking different OS versions of my one Graphics library. Is this advised? Or are macros more common?

Let us take a Graphics library as an example, containing a windows-class and a sprite-class.

Now, our code owns a Graphics component having the sprite-class as a member.

I can simply change the library binaries

Would it be better to create a Sprite-wrapper instead? So, my Graphics component can call methods to obtain coordinates without really knowing what kind of object it is working with.

As far as I know, decoupling is generally advised, just curious to know when it is too much.

Thanks for reading : )!

Advertisement

How I handle Platform Specific code is quite simple. I usually try to ambiguate the types the class relies on using preprocessor directives like #ifdef/#endif. So for instance I could do this


Struct WindowInstance
{
#ifdef WIN32
    HINSTANCE hInstance
#elif
    //another platform API handle, like XWindows
#endif
};

struct WindowHandle
{ 
#ifdef WIN32
    HWND hWnd;
#elif
    //another platform API handle, like XWindows
#endif
};

I then use these types in the appropriate header so for the above example I would use that for a Window Class


class Window
{
public:
    Window(const WindowInstance&);
    ~Window();
public:
     const WindowHandle& getHandle() const;
     //ect...
private:
    WindowInstance& winInstance;
    WindowHandle&   winHandle;
};

This enables me to create platform independent headers, and leave the platform specifics to the implementation file. There are a lot of ways you can approach this problem, you could go the virtual function route, but I find this to be clean, and simple.

Marcus Hansen

I was wondering if it is common practice to wrap around classes from external libraries in order to interchange such library by another.

Not common, but it happens.

Generally it is a waste of time. You aren't going to swap out a major library very often. You don't say "Today we're using PhysX, but we're swapping it out with Bullet next week. Maybe in a few more weeks we'll swap it out with something else, so keep it flexible!"

If you end up swapping libraries, usually it is a one-shot transition.

That said, when working with cross-platform code bases it can make sense to abstract away specific systems. The effort is large since you are basically building a shared interface plus an adapter for each one. So if you need three of them, you are building a shared interface plus writing and testing three additional code bases.

There are many beginners who commonly push for multiple renderers, wanting perhaps an OpenGL ES 2.0 version and an OpenGL 4.0 version and a D3D9 version and a D3D11 version and a D3D12 version and a Vulcan version... Instead of spending their time making a game they spend their days writing and rewriting a single component that doesn't work very well.

It is common to wrap things if you intend to change them, It's called Abstraction.

In terms of basic design concepts, you should abstract something if you change it a lot.

For example a window handle, for different OSs it is different, but the abstracted beahvior is the same (Open window, Close window, Change title, Change width/height, etc...)

In terms of high level design concepts it's not the best solution. Since it would take much effort to actually implement this abstraction in a nice way.

It's a good solution if you want a very extendable library (such as support for more operation systems and plugins).

But I fear you gain too little from it- In terms of maintaining the library, upgrading code and developing new features.

So if you look at it in smaller details, it's worthwile to check if preprocessors are a better way to change behavior than splitting it into different libraries and interfaces.

The key is measure twice cut once.

Because if you decide now to develop for multiple operation systems but at the end only windows users will actually play, then why did you even go cross platform?

I was wondering if it is common practice to wrap around classes from external libraries in order to interchange such library by another.

Do this work when you know you need to interchange the library, not before. You don't save any time by doing it up front, all you do is change which part of your code you'll need to alter next time. If anything it's worse to do it up front because you don't have enough experience of each alternative yet to be able to create an adequate abstraction for them both.

If you want to have multiple target platforms, the first thing you need is an easy way to test your program on every relevant platform. Without that, you may think that your program is multi-platform but you might be fooling yourself.

I like using SFML, which neatly wraps a lot of platform-specific things for you. For anything else, I have a header file called something like "platform-specific.hpp" which contains prototypes of free functions (I typically only need a few), and several corresponding implementation files, one per platform ("windows_platform.cpp", "posix_platform", etc.). I then use only the appropriate implementation file in each makefile or project description.

Either use an off-the-shelf library that provides such an abstraction layer (say, something like SDL for window/input management, of bgfx for renderer abstraction), or don't write these abstractions till you need them.

It's close to impossible to write such abstraction layers until you actually know the requirements, and you won't know the requirements till you write the game the first time. Writing abstractions first will just stick you in an endless cycle of rewrites as you discover new features you need to abstract over.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement