How to Load a Shared Object in C++

How do I load a shared object in C++?

There are two ways of loading shared objects in C++

For either of these methods you would always need the header file for the object you want to use. The header will contain the definitions of the classes or objects you want to use in your code.

Statically:

#include "blah.h"
int main()
{
ClassFromBlah a;
a.DoSomething();
}

gcc yourfile.cpp -lblah

Dynamically (In Linux):

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("libm.so", RTLD_LAZY);
if (!handle) {
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
dlerror(); /* Clear any existing error */
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
return 0;
}

*Stolen from dlopen Linux man page
The process under windows or any other platform is the same, just replace dlopen with the platforms version of dynamic symbol searching.

For the dynamic method to work, all symbols you want to import/export must have extern'd C linkage.

There are some words Here about when to use static and when to use dynamic linking.

(solved) C++ Load one Shared Object with dependencies and access their functions

As a start, change the order of the arguments in the link-commands

g++ -g -shared -o libtest2.so -L. lib2.o -ltest1
g++ -g -shared -o libtest3.so -L. lib3.o -ltest1 -ltest2

Note: it's not necessary with every linker, but the newer gold linker only resolves "from-left-to-right". Also there's a -Wl,--no-undefined option, which is very useful to catch these error.

Then add rpath into these commands so that the shared objects find their dependencies run-time:

g++ -g -shared -o libtest2.so "-Wl,-rpath,${PWD}" -L. lib2.o -ltest1
g++ -g -shared -o libtest3.so "-Wl,-rpath,${PWD}" -L. lib3.o -ltest1 -ltest2

After linkage, readelf -d should show the RPATH like this:

$ readelf -d libtest3.so |head -n10

Dynamic section at offset 0xdd8 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libtest1.so]
0x0000000000000001 (NEEDED) Shared library: [libtest2.so]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000001d (RUNPATH) Library runpath: [/home/projects/proba/CatMan]

(Also there is libtool to deal with shared libraries.)

Mind you, because of name-mangling, the following change should be performed (though it is compiler-specific)

- OpenSymbol(pHandle, "printBase");
+ OpenSymbol(pHandle, "_ZN4Base9printBaseEv");

How can a shared library (.so) call a function that is implemented in its loader code?

You'll need make a register function in your .so so that the executable can give a function pointer to your .so for it's later used.

Like this:

void in_main_func () {
// this is the function that need to be called from a .so
}

void (*register_function)(void(*)());
void *handle = dlopen("libmylib.so");

register_function = dlsym(handle, "register_function");

register_function(in_main_func);

the register_function needs to store the function pointer in a variable in the .so where the other function in the .so can find it.

Your mylib.c would the need to look something like this:

void (*callback)() = NULL;

void register_function( void (*in_main_func)())
{
callback = in_main_func;
}

void function_needing_callback()
{
callback();
}

Loading shared library twice

You need to use dlmopen to achieve this sort of isolation:

// No need for RTLD_LOCAL, not sure about RTLD_DEEPBIND
lib1 = dlmopen (LM_ID_NEWLM, "mylib.so", RTLD_LAZY | RTLD_DEEPBIND);

How to load a shared library without loading its dependencies?

Well, variables are still resolved even with RTLD_LAZY, so in general you do need all the libraries to be linked. Seems like you should create a stub libbar.so.1 that has no functionality and can be found by the linker.

Is there a way to load a Linux shared library into a specific memory location?

I think that the prelink program may actually demonstrate a way to do this if you are willing to modify the library. The goal is to modify the library so that it will have a preferred address. The intent of prelink is to do this for performance, but my suspicion is that it can be modified to work for your use case.
Note that you will never be guaranteed that this will happen in the general case, but in controlled cases you may be able to guarantee that it will happen.
Certainly examining prelink will allow you to understand the parts of elf involved and make a more informed determination about whether it is possible.
http://en.wikipedia.org/wiki/Prelink#
Or see http://packages.qa.debian.org/prelink for the sources in Debian.



Related Topics



Leave a reply



Submit