Extend a dynamic linked shared library?

I'm new to C, so sorry for the lack of knowledge (my C-book here is really massive :)

I would like to expand the shared library (libcustomer.so) with a closed source, but well-known api.

Is this possible?

  • rename libcustomer.so to liboldcustomer.so
  • create an extended shared library libcustomer.so (so others implicitly use the extended one)
  • link liboldcustomer.so to my extended libcustomer.so via -loldcustomer
  • forward any unrealized methods directly to the old "liboldcustomer.so"

I don't think this will work (the name is compiled into .so, right?). But what is the alternative?

For # 4: is there a general way to do this, or do I need to write a method called the old one and forward the call (how?)?

Since the original libcustomer.so (= liboldcustomer.so) may change from time to time, all of these things should work dynamically.

For security reasons, our system does not have LD_PRELOAD (otherwise I would take this :().

Think about advanced validation checks and some NPE enhancements.

Thanks in advance for your help!

EDIT:

I just implement my extension as shown in the answer, but at the moment I have one unhandled case:

How can I "proxy" structures from an extended library?

For example, I have this:

customer.h:

struct customer;

customer.c:

struct customer {
    int children:1;
    int age;
    struct house *house_config;
};

Now, in my customer-extension.c, I am writing all the public methods of the form customer.c, but how can I “skip” the structures?

Thanks so much for your time and help!

+5
source share
1 answer

So you have OldLib with

void func1();
int  func2();
... etc

4 .

NewLib :

void your_func1();

void (*old_func1_ptr)() = NULL;
int  (*old_func2_ptr)() = NULL;

void func1()
{
    // in case you don't have static initializers, implement lazy loading
    if(!old_func1_ptr)
    {
       void* lib = dlopen("OldLibFileName.so", RTLD_NOW);
       old_func1_ptr = dlsym(lib, "func1");
    }

    old_func1_ptr();
}

int func2()
{
    return old_func2_ptr();
}

// gcc extension, static initializer - will be called on .so load
// If this is not supported, then you should call this function
// manually after loading the NewLib.so in your program.
// If the user of OldLib.so is not _your_ program,
// then implement lazy-loading in func1, func2 etc. - check function pointers for being NULL
// and do the dlopen/dlsym calls there.
__attribute__((constructor))
void static_global_init()
{
   // use dlfcn.h
   void* lib = dlopen("OldLibFileName.so", RTLD_NOW);

   old_func1_ptr = dlsym(lib, "func1");
   ...
}

static_global_init func_ptr , API. NewLib , , OldLib.

+5

All Articles