2014-08-27 70 views
2

我想让一个共享库从它正在加载到的进程调用一个函数。该库是用C语言编写的,即C++中的“内核”。dlopen不能找到demangled符号

kernel.cpp:

#include <stdio.h> 
#include <dlfcn.h> 

typedef void(*func_t)(); 

extern "C" { 
     void test(); 
} 

int main() { 
     char *error; 
     void *handle = dlopen("./library.so", RTLD_LAZY); 
     if((error = dlerror()) != NULL) { 
       fprintf(stderr, "%s\n", error); 
       return 1; 
     } 
     func_t init = (func_t)dlsym(handle, "init"); 
     if((error = dlerror()) != NULL) { 
       fprintf(stderr, "%s\n", error); 
       return 1; 
     } 
     init(); 

     return 0; 
} 

void test() { 
     fprintf(stderr, "test() called.\n"); 
} 

LIBRARY.C:

#include <stdio.h> 

void test(); 

void init() { 
     fprintf(stderr, "init() called.\n"); 
     test(); 
} 

生成文件:

all: 
     g++ -ldl kernel.cpp -o kernel 
     gcc -fpic -shared library.c -o library.so 
     ./kernel 

objdump的-x内核

SYMBOL TABLE: 
... 
000000000040088b g  F .text 0000000000000024 test 

程序运行后,我得到下面的输出:

init() called. 
./kernel: symbol lookup error: ./library.so: undefined symbol: test 

如果我改变的dlopen使用RTLD_NOW,我得到:

./library.so: undefined symbol: test 

为什么难以找到该符号时,它显然是图书馆没有损坏,坐在那里?

+1

当你说这声明'extern“C”',但是当你定义它时,你不会。 – doctorlove 2014-08-27 12:03:59

回答

5

默认情况下不会导出可执行文件的符号。

您需要-export动态链接器标志用于链接可执行文件:

g++ -ldl -Wl,-export-dynamic kernel.C -o kernel 

从LD手册页,它描述了确切的情况报价:

If you use "dlopen" to load a dynamic object which needs to refer 
back to the symbols defined by the program, rather than some other 
dynamic object, then you will probably need to use this option when 
linking the program itself. 
+0

你可以使用'g ++ -Wall -rdynamic kernel.C -o kernel -ldl',因为'-rdynamic'和'-Wl,-export-dynamic'是一样的 – 2014-08-27 12:35:56

+0

但是这个解决了,但这次我得到 library.so:undefined symbol:init 和文件名不是kernel.C其kernel.cpp – Adarsh 2014-08-27 12:59:30

+0

感谢您的帮助! -rdynamic是我所需要的。 – 2014-08-27 13:15:26