Avoiding link time dependencies

Discussion in 'Game Development (Technical)' started by ggambett, Apr 24, 2008.

  1. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    I've integrated ffmpeg with our framework so we can play AVI within our games. I have to link with a couple of new libraries and ship a couple of DLLs for this to work.

    The thing is, most of our games don't play AVI, so these DLLs aren't needed at all, but the game will refuse to start without them, just because the framework *may* use them (the linker won't remove that because using or not using them depends on an if(), ie "if(filename contains ".avi") then...")

    The two options I can think of are a) not linking to the libs and using LoadLibrary/dlopen to get pointers to the functions I need, or b) having this dependency as a separate library (framework-avisupport) which registers an "AVI handler" with some global list in the framework on startup.

    I don't like a) because it's tedious and error prone, and I don't like b) because it uses static constructors where order of execution can be tricky. Solution b) looks like the lesser of evils, but I still think it's evil.

    Any other ideas?
     
  2. Scorpio

    Indie Author

    Joined:
    Aug 1, 2004
    Messages:
    101
    Likes Received:
    0
    In this situation, we always go with option A (unless there are hundreds of functions that are used--which has never been the case for us (fortunately!)).

    Although it's a little tedious to setup, once you have it all coded (and you can make a class to hide it all), it works very well and fails very gracefully if the required stuff is not installed. What type of errors are you worried about?

    Since option A is how we do it, I don't have any other suggestions for you (but interested in seeing some as well).
    -Scorpio
     
  3. GeneralGrant

    GeneralGrant New Member

    Joined:
    Jan 17, 2008
    Messages:
    117
    Likes Received:
    0
    If you use Visual Studio you can use delay loaded dlls (linker switch). The dll is only loaded if an exported function is called at runtime. You can’t, however, unload the dll once loaded.
     
  4. jpoag

    jpoag New Member

    Joined:
    Mar 15, 2008
    Messages:
    806
    Likes Received:
    0
    http://msdn2.microsoft.com/en-us/library/96c1b5cf(VS.80).aspx

    But I'm with Scorpio, you'll be able to fail gracefully, or define NOOP situations.

    The SexyAppFramework uses the BASS music library, but for demos, when we don't need sound, we can say something like mNoSoundNeeded = true;

    When the Framework is in the Init() stage, it checks this parameter and if it's set to true, then it loads up a MusicInterface that does nothing, otherwise it loads up Bass.dll and returns an instance to a base music wrapper.

    There's even a third option to return a FMod interface later on, but I digress.

    If you create an interface for the library, then why no go one extra step and abstract the interface? That way your IVideoPlayer can have NOOP implementations of the methods.
     
    #4 jpoag, Apr 24, 2008
    Last edited: Apr 24, 2008
  5. GeneralGrant

    GeneralGrant New Member

    Joined:
    Jan 17, 2008
    Messages:
    117
    Likes Received:
    0
    I stand corrected. :)
     
  6. jpoag

    jpoag New Member

    Joined:
    Mar 15, 2008
    Messages:
    806
    Likes Received:
    0
    lol, sorry mate, but that was the first link I saw on the page you posted. Really helpful, and I didn't know that you delay dll loading before you told me. ;)
     
  7. jcottier

    jcottier New Member

    Joined:
    Jul 12, 2006
    Messages:
    1,385
    Likes Received:
    0
    Yes! This is what I am doing too.

    JC
     
  8. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    Replying to directly to Scorpio and indirectly to everyone else... I want this to work on Linux, Mac and Windows. So no VS-specific solutions, and loading the libraries by hand is not only tedious, but tedious times three :)
     
  9. Kayamon

    Kayamon New Member

    Joined:
    Sep 4, 2007
    Messages:
    7
    Likes Received:
    0
    How about b) where you put the AVI code in a separate library.

    But rather than use a static constructor, the user would simply call:

    {
    EnableAVIPlayback(); // or something
    }
     
  10. GolfHacker

    GolfHacker Member

    Joined:
    Oct 4, 2006
    Messages:
    1,073
    Likes Received:
    0
    I've used delayed DLL loading on Windows before. It isn't so bad, and is an ideal solution.

    In *nix systems, you would have a .so (shared object) instead of a .dll. Shared objects are only loaded when needed, so you shouldn't need to do anything special for Linux.

    Not sure about Mac, you'll need to refer to the documentation on the Apple developer site, or possible ask the folks at www.idevgames.com.
     
  11. 20thCenturyBoy

    Original Member

    Joined:
    Sep 23, 2004
    Messages:
    178
    Likes Received:
    0
    What's wrong with just shipping the dlls and be done with it? License issues?
     
  12. ChrisP

    Indie Author

    Joined:
    Feb 5, 2007
    Messages:
    971
    Likes Received:
    0
    Make that tedious times two; Mac OS X uses dlopen/dlsym (the Unix/Linux way) since version 10.3. :) So unless you're set on supporting 10.2 and earlier, you only need to write the code twice.

    More than that, dlopen/LoadLibrary and dlsym/GetProcAddress and whatever the unloading functions are called (I forget!) are practically interchangeable. Just write three small wrapper functions, and hey presto, you have a cross-platform dynamic library loading routine. This is exactly the approach used for Mayhem Intergalactic. I package the DLLs/SOs/frameworks with the game, and simply call functions to load the library and the functions I need. Slightly tedious, yes, but at least it's now tedious times one!

    The paths to the libraries will obviously change on each OS. This isn't difficult at all. I use "something.dll" on Windows, "./something.so" on Linux (the ./ is important; Linux doesn't link to DLLs in the current directory if you simply name the file without the directory part), and "./frameworks/Something.framework/Something" on Mac OS X.

    I haven't actually released the Linux or Mac versions yet, but they work. Mostly. The bits that don't work aren't related to library loading. :)
     
  13. GolfHacker

    GolfHacker Member

    Joined:
    Oct 4, 2006
    Messages:
    1,073
    Likes Received:
    0
    Oops, thanks ChrisP - I missed the part about avoiding link dependencies (heh, the whole title of the thread). If you just want to not load a .so on Linux that your game doesn't use, you don't need to do anything special - it loads as needed. But if you don't want to have to link against it, and/or have the executable start without this .so present, you absolutely have to use dlsym.

    Sorry, guess my first post in here wasn't too useful. :(
     
  14. Huge

    Original Member

    Joined:
    Sep 22, 2005
    Messages:
    142
    Likes Received:
    0
    I like option A - it is like a "plugin" system.
    To make life easier on yourself, you can define a c++ abstact base class with virtual functions. Implement this inside a "glue" DLL by calling the appropriate library funtions, thus binding your (very small) glue dll to the other dlls. Finally, add a single static "c-linkage" function "CreateInterface" that simply "new"s a concrete implementation of your base class. This way you only have to resolve a single function pointer (CreateInterface) since the virtual function pointers will be in the vtable.
    If you are feeling paranoid, make your first function "GetVersion".

    Huigh
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer