Description
This is a sample of how C++ call a dlopen function.
1. mypgm.cpp : the main program
2. mylib.cpp: the main library
mypgm.cpp
#include <stdio.h>
#include <dlfcn.h>
typedef char * (* myFun_t)(const char *, int &);
const char * LIB = "libmylib.so";
const char * FUN = "myFun";
//const char * FUN = "_Z5myFunPKcRi";
int main(int argc, char * argv[]) {
void * handle = dlopen(LIB, RTLD_NOW);
if (handle == NULL) {
printf("Cannot load library: %s\n", LIB);
return -1;
}
myFun_t myFun = (myFun_t) dlsym(handle, FUN);
if (myFun == NULL) {
printf("Cannot get function: %s\n", FUN);
return -1;
}
for (int i = 0; i < 3; i++) {
int length = i;
char * buffer = myFun("any", length);
if (buffer == NULL) {
printf("Failed to call myFun\n");
return -1;
}
else {
printf("CALLER: myFun() return [%d],[%s]\n", length, buffer);
}
}
int ret = dlclose(handle);
if (ret != 0) {
printf("Cannot call dlclose\n");
return -1;
}
return 0;
}
mylib.cpp
#include <stdio.h>
//extern "C" char * myFun(const char * filename, int & len);
//extern "C" { char * myFun(const char * filename, int & len); }
extern "C"
char * myFun(const char * filename, int & len) {
static int count = 0;
printf("CALLEE: myFun(len=[%d]), count=[%d]\n", len, ++count);
len = count;
char * ret = "aaa";
return ret;
}
makefile
1 2 TARGET=mypgm libmylib.so 3 4 all: $(TARGET) 5 6 mypgm: mypgm.cpp 7 g++ -o $@ $< -ldl 8 9 libmylib.so: mylib.cpp 10 g++ -fPIC -shared -o $@ $< 11 12 .PHONY: clean 13 14 clean: 15 -rm -rf $(TARGET)
* Execute
$ make g++ -o mypgm mypgm.cpp -ldl g++ -fPIC -shared -o libmylib.so mylib.cpp $ ./mypgm CALLEE: myFun(len=[0]), count=[1] CALLER: myFun() return [1],[aaa] CALLEE: myFun(len=[1]), count=[2] CALLER: myFun() return [2],[aaa] CALLEE: myFun(len=[2]), count=[3] CALLER: myFun() return [3],[aaa]
C++ mangle
The function myFun defined in mylib.cpp must be declared with "extern C", otherwise, the caller could not find the symbol, because C++ will mangle the symbol name.
Take above example: if there is no "extern C", the myFun function will be given a name as "_Z5myFunPKcRi", so when caller (mypgm) use
myFun_t myFun = (myFun_t) dlsym(handle, "myFun") to find the function symbol, it will not get the expected result, instead the caller can use
myFun_t myFun = (myFun_t) dlsym(handle, "_Z5myFunPKcRi"); to get the correct function.
The mangled symbol name can be get through:
$ nm libmylib.so | grep myFun
00000000000005ac T _Z5myFunPKcRi
0000000000200914 b _ZZ5myFunPKcRiE5count