Creating a wrapper to two identical shared libraries - Unix

This is a discussion on Creating a wrapper to two identical shared libraries - Unix ; Hi, I am working on a large software project where we need to program for two identical devices. Let's call them A and B. We have already coded all of the functionality of A and created a shared library out ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: Creating a wrapper to two identical shared libraries

  1. Creating a wrapper to two identical shared libraries

    Hi,

    I am working on a large software project where we need to program for
    two identical devices. Let's call them A and B. We have already
    coded all of the functionality of A and created a shared library out
    of this code that we can call libA.so. To support device B we re-
    compile this code and create a second shared library: libB.so. Now we
    have two shared libraries that can control their respective devices
    independently.

    The problem that we are having is that it would be advantageous in
    certain cases to access either or both devices from the same piece of
    code. However, since libA and libB have identical method names how
    can we link these to the same code to access them? I'd like to create
    a wrapper class that gives access to both shared libraries. Ideally,
    the functionality of the wrapper would give global access to the
    libraries through an array index so that if I make a call like lib[0]-
    >GetDeviceType(); it would link to libA and if I make a call like


    lib[1]->GetDeviceType(); it would link to libB. Of course the index
    into the lib array could vary at run-time.

    Any suggestions on this or design ideas that might work? Can this
    work at all?

    Kevin

  2. Re: Creating a wrapper to two identical shared libraries

    Kevin Sookocheff writes:
    > I am working on a large software project where we need to program for
    > two identical devices. Let's call them A and B. We have already
    > coded all of the functionality of A and created a shared library out
    > of this code that we can call libA.so. To support device B we re-
    > compile this code and create a second shared library: libB.so. Now we
    > have two shared libraries that can control their respective devices
    > independently.
    >
    > The problem that we are having is that it would be advantageous in
    > certain cases to access either or both devices from the same piece of
    > code. However, since libA and libB have identical method names how
    > can we link these to the same code to access them? I'd like to create
    > a wrapper class that gives access to both shared libraries. Ideally,
    > the functionality of the wrapper would give global access to the
    > libraries through an array index so that if I make a call like lib[0]-
    >>GetDeviceType(); it would link to libA and if I make a call like

    >
    > lib[1]->GetDeviceType(); it would link to libB. Of course the index
    > into the lib array could vary at run-time.
    >
    > Any suggestions on this or design ideas that might work?


    An obvious idea would be to dlopen each of the libraries and store the
    handles in some 'library interface structure'. This library interface
    structure would contain a table of function pointers representing the
    various interfaces provided by the libraries, with each function
    pointer initially set to a 'fixup' routine. When the fixup routine is
    called, it would use the library-specific dlopen-handle to do a
    symbol lookup for a particular function in one of the libraries,
    storing the returned function pointer into the table position and then
    'forwarding' the call to it.

    This should be fairly easy to code in assembly and would need
    'suitable compiler support' otherwise.

  3. Re: Creating a wrapper to two identical shared libraries

    In article <7501b37a-82a2-446d-9533-772bb161bd53@h11g2000prf.googlegroups.com>,
    Kevin Sookocheff wrote:

    >The problem that we are having is that it would be advantageous in
    >certain cases to access either or both devices from the same piece of
    >code. However, since libA and libB have identical method names how
    >can we link these to the same code to access them? I'd like to create
    >a wrapper class that gives access to both shared libraries. Ideally,
    >the functionality of the wrapper would give global access to the
    >libraries through an array index so that if I make a call like lib[0]-
    >>GetDeviceType(); it would link to libA and if I make a call like

    >
    >lib[1]->GetDeviceType(); it would link to libB. Of course the index
    >into the lib array could vary at run-time.
    >
    >Any suggestions on this or design ideas that might work? Can this
    >work at all?



    Somebody who's actually done it on Unix (I've only done this on other
    platforms) can comment on the details, but here's a design idea that
    I've used successfully.


    Set up a struct with a bunch of function pointers (if you're using C++,
    you can either hide it behind a class (with the same underlying
    mechanism), or just have a single call that initializes an interface
    object and returns a pointer to that; the former can be more robust,
    but the latter will be simpler if you have some other way to avoid
    interface mismatches):
    --------
    struct lib_interface
    {
    int (*GetDeviceType)(void);
    };
    --------

    Instead of linking against the dynamic library, write code to load it
    at runtime:
    --------
    struct lib_interface *load_interface(const char *libname)
    {
    struct lib_interface *ret=malloc(sizeof *ret);
    if(!ret)
    return NULL;
    /*Load library identified by libname*/

    ret->GetDeviceType=get_entry_point(/*...*/);

    /*Check for whether any entry point load fails and deal with
    it sensibly
    */

    return ret;
    }
    --------

    Then call the interface loader as part of the program initialization:
    --------
    lib[0]=load_interface("libA.so");
    if(!lib[0])
    fatal("Can't load libA.so");
    lib[1]=load_interface("libB.so");
    if(!lib[1])
    fatal("Can't load libB.so");
    --------

    This transforms your problem from avoiding link-time symbol conflicts
    to avoiding load-time symbol conflicts; I don't know enough to speak
    with any generality, but, at least on the only platform I've ever tried
    it, run-time loading doesn't care whether some other library you've
    loaded exports the same symbols as the one you're loading.

    This also lets your program decide it can limp along if some library
    can't be loaded, or if some symbols can't be found in one of the
    library it loads, instead of having the shared library loader fail
    before your code runs.


    dave

    --
    Dave Vandervies dj3vande at eskimo dot com

    Dadaist: 3 is prime, 5 is prime, 7 is prime, banana, 11 is prime...
    --Michael Wojcik in comp.lang.c

  4. Re: Creating a wrapper to two identical shared libraries

    Kevin Sookocheff writes:
    >Hi,
    >
    >I am working on a large software project where we need to program for
    >two identical devices. Let's call them A and B. We have already
    >coded all of the functionality of A and created a shared library out
    >of this code that we can call libA.so. To support device B we re-
    >compile this code and create a second shared library: libB.so. Now we
    >have two shared libraries that can control their respective devices
    >independently.
    >
    >The problem that we are having is that it would be advantageous in
    >certain cases to access either or both devices from the same piece of
    >code. However, since libA and libB have identical method names how
    >can we link these to the same code to access them? I'd like to create
    >a wrapper class that gives access to both shared libraries. Ideally,
    >the functionality of the wrapper would give global access to the
    >libraries through an array index so that if I make a call like lib[0]-
    >>GetDeviceType(); it would link to libA and if I make a call like

    >
    >lib[1]->GetDeviceType(); it would link to libB. Of course the index
    >into the lib array could vary at run-time.
    >
    >Any suggestions on this or design ideas that might work? Can this
    >work at all?
    >


    My mainframe simulator supports multiple different I/O channel
    types, each of which (e.g. card reader, train printer, disk, tape,
    etc.) is implemented as a shared object (.so). Each .so has
    the same function (get_device()) and is loaded using the dlopen(3)
    library function. The per-library get_device() function pointer
    is retreived with dlsym() and invoked. It returns a pointer to the
    channel base class (which is subclassed for the specific device type)
    which implements the standard read/write/test/cancel channel functions.

    scott

+ Reply to Thread