view dwt/dwthelper/Loader.d @ 238:380bad9f6852

reverted char[] to String
author Frank Benoit <benoit@tionex.de>
date Mon, 05 May 2008 00:42:55 +0200
parents 384b3a0c9cd7
children
line wrap: on
line source

/*****************************************************************************

    license:

    version:

             Dynamic loader for gtk symbol names

    History: 2004-12-11 initial version by John Reimer
             2005-02-21 class and symbol names change; versioning modification
             2005-05-05 linux fixes
             2007-12-23 source cleanup
             2007-12-30 merge Paths.d into Loader.d
             2008-01-05 Tango only version using tango.sys.SharedLib

    Note:   Design inspired by Kris Bell's ICU.d, the dynamic loader from
            an early version of mango

******************************************************************************/

module dwt.dwthelper.Loader;

import dwt.dwthelper.utils;

private import  tango.io.Stdout,
                tango.sys.SharedLib;
                
/*****************************************************************************

*****************************************************************************/

enum LIBRARY
{
    ATK,
    CAIRO,
    GDK,
    GDKPIXBUF,
    GLIB,
    GMODULE,
    GOBJECT,
    GTHREAD,
    GTK,
    PANGO,
    GLGDK,
    GLGTK,
    GL,
    GLU,
    GLEXT,
    GDA,
    GLADE,
    GSV,
    GSTREAMER,
    GSTINTERFACES
}

/*****************************************************************************

*****************************************************************************/

version (Windows)
{
    const String[LIBRARY.max+1] importLibs = [
        LIBRARY.ATK:            "libatk-1.0-0.dll",
        LIBRARY.CAIRO:          "libcairo-2.dll",
        LIBRARY.GDK:            "libgdk-win32-2.0-0.dll",
        LIBRARY.GDKPIXBUF:      "libgdk_pixbuf-2.0-0.dll",
        LIBRARY.GLIB:           "libglib-2.0-0.dll",
        LIBRARY.GMODULE:        "libgmodule-2.0-0.dll",
        LIBRARY.GOBJECT:        "libgobject-2.0-0.dll",
        LIBRARY.GTHREAD:        "libgthread-2.0-0.dll",
        LIBRARY.GTK:            "libgtk-win32-2.0-0.dll",
        LIBRARY.PANGO:          "libpango-1.0-0.dll",
        LIBRARY.GLGDK:          "libgdkglext-win32-1.0-0.dll",
        LIBRARY.GLGTK:          "libgtkglext-win32-1.0-0.dll",
        LIBRARY.GL:             "opengl32.dll",
        LIBRARY.GLU:            "glu32.dll",
        LIBRARY.GDA:            "libgda-2.dll",
        LIBRARY.GLADE:          "libglade-2.0.dll",
        LIBRARY.GSV:            "libgtksourceview-1.0-0.dll",
        LIBRARY.GSTREAMER:      "libgstreamer-0.10.dll",
        LIBRARY.GSTINTERFACES:  "libgstinterfaces-0.10.dll"
    ];
}

/*****************************************************************************

*****************************************************************************/

version(linux)
{
    const String[LIBRARY.max+1] importLibs = [
        LIBRARY.ATK:            "libatk-1.0.so",
        LIBRARY.CAIRO:          "libcairo.so.2",
        LIBRARY.GDK:            "libgdk-x11-2.0.so",
        LIBRARY.GDKPIXBUF:      "libgdk_pixbuf-2.0.so",
        LIBRARY.GLIB:           "libglib-2.0.so",
        LIBRARY.GMODULE:        "libgmodule-2.0.so",
        LIBRARY.GOBJECT:        "libgobject-2.0.so",
        LIBRARY.GTHREAD:        "libgthread-2.0.so",
        LIBRARY.GTK:            "libgtk-x11-2.0.so",
        LIBRARY.PANGO:          "libpango-1.0.so",
        LIBRARY.GLGDK:          "libgdkglext-x11-1.0.so",
        LIBRARY.GLGTK:          "libgtkglext-x11-1.0.so",
        LIBRARY.GL:             "libGL.so",
        LIBRARY.GLU:            "libGLU.so",
        LIBRARY.GLEXT:          "libGL.so",
        LIBRARY.GDA:            "libgda-2.so.3",
        LIBRARY.GLADE:          "libglade-2.0.so",
        LIBRARY.GSV:            "libgtksourceview-1.0.so",
        LIBRARY.GSTREAMER:      "libgstreamer-0.10.so",
        LIBRARY.GSTINTERFACES:  "libgstinterfaces-0.10.so"
    ];
}

/*****************************************************************************

    getLibraryPath -- place holder for future expansion

******************************************************************************/


version(Windows)
{
    String getLibraryPath()
    {
            return "\\Program Files\\GTK2-Runtime\\lib\\";
    }
}

/*****************************************************************************

    getLibraryPath is empty for linux because default path is known by ld

******************************************************************************/

version(linux)
{
    String getLibraryPath() { return ""; }
}

/*****************************************************************************

    ProcLink is used to record the library, function, and function name
    that will be loaded by the dynamic loader.

******************************************************************************/

public struct Symbol
{
    String  name;
    void**  pointer;
}

/*****************************************************************************

    The Linker class: handles loading of the library and exported functions

******************************************************************************/

public class Linker
{
    static String[][String] loadFailures;

    /*************************************************************************

        Gets all the failed loads for a specific library.  This is filled in
        only if the default onFailure method is used during load.

        returns: an array of the names that failed to load for a specific
        library or null if none was found.

    **************************************************************************/

    public static String[] getLoadFailures(String libName)
    {
        if ( libName in loadFailures )
        {
            return loadFailures[libName];
        }
        else
        {
            return null;
        }
    }

    /*************************************************************************

        Loads all libraries. This is filled in only if the default onFailure
        method is used during load.

        returns: an array of the library names.

    **************************************************************************/

    public static String[] getLoadLibraries()
    {
        return loadFailures.keys;
    }

    /*************************************************************************

        isPerfectLoad -- Checks if any symbol failed to load.
        Returns: true if ALL symbols loaded.

    **************************************************************************/

    public static bool isPerfectLoad()
    {
        return loadFailures.keys.length == 0;
    }

    /*************************************************************************

    **************************************************************************/

    public static void dumpFailedLoads()
    {
        foreach ( String lib ; Linker.getLoadLibraries() )
        {
            foreach ( String symbol ; Linker.getLoadFailures(lib) )
            {
                version(Tango)
                    Stdout.formatln("failed ({}) {}", lib, symbol).newline;
            }
        }
    }

    /*************************************************************************

    **************************************************************************/

    private SharedLib primaryLib;
    private SharedLib alternateLib;

    private String  libraryName;
    private String  alternateLibraryName;

    alias void function( String libraryName, String symbolName, String message=null) FailureCallback;

    private FailureCallback onLoadFailure;

    /*************************************************************************

    **************************************************************************/

    this( String libraryName, String alternateLibraryName=null )
    {
        this(libraryName, alternateLibraryName, &(Linker.defaultFail));
    }

    /*************************************************************************

    **************************************************************************/

    this (String libraryName, String alternateLibraryName, FailureCallback fn )
    {
        this.libraryName = libraryName;
        this.alternateLibraryName = alternateLibraryName;
        onLoadFailure = fn;

        SharedLib.throwExceptions = false;

        primaryLib = SharedLib.load( this.libraryName );
        
        version(linux)
        {
            if (this.primaryLib is null)
                primaryLib = SharedLib.load( this.libraryName ~ ".0\0" );
        }
            
        if ( alternateLibraryName !is null )
        {
            alternateLib = SharedLib.load( this.alternateLibraryName );
        }
        
        if (primaryLib is null)
        {
            throw new Exception("Library load failed: " ~ libraryName);
        }
    }

    /*************************************************************************

        Default load failure callback. Logs the symbols that failed to load.

    **************************************************************************/

    static void defaultFail( String libraryName, String symbolName, String message=null )
    {
        if ( !(libraryName in loadFailures) )
        {
            String[] cc;
            loadFailures[libraryName] = cc;
        }

        loadFailures[libraryName] ~= symbolName.dup;
    }

    /*************************************************************************

        Loads all the symbols for this library.

    **************************************************************************/

    void link( inout Symbol[] symbols )
    {
        foreach( Symbol link; symbols )
        {
            *link.pointer = primaryLib.getSymbol ( (link.name~"\0").ptr);

            if (*link.pointer is null)
            {
                if ( alternateLib !is null )
                {
                    *link.pointer = alternateLib.getSymbol( (link.name~"\0").ptr);
                    Stdout("Loader.Linker.link trying alternate lib: ", link.name).newline;
                }
                if (*link.pointer is null)
                {
                    onLoadFailure( libraryName, link.name );
                }
            }
        }
    }

}