我写了一个程序来打开自己
void hello() { printf("hello world\n"); } int main(int argc, char **argv) { char *buf="hello"; void *hndl = dlopen(argv[0], RTLD_LAZY); void (*fptr)(void) = dlsym(hndl, buf); if (fptr != NULL) fptr(); dlclose(hndl); }
但我得到“segemention故障”的错误我testing了这个程序与.so库,它的工作原理,但不能让它与自己的工作
你需要编码:
// file ds.c #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> void hello () { printf ("hello world\n"); } int main (int argc, char **argv) { char *buf = "hello"; void *hndl = dlopen (NULL, RTLD_LAZY); if (!hndl) { fprintf(stderr, "dlopen failed: %s\n", dlerror()); exit (EXIT_FAILURE); }; void (*fptr) (void) = dlsym (hndl, buf); if (fptr != NULL) fptr (); else fprintf(stderr, "dlsym %s failed: %s\n", buf, dlerror()); dlclose (hndl); }
仔细阅读dlopen(3) ,总是检查dlopen
& dlsym
函数的成功,并在失败时使用dlerror
。
并用上面的ds.c
文件编译
gcc -std=c99 -Wall -rdynamic ds.c -o ds -ldl
不要忘记 – 要获得所有的警告和-rdynamic
标志(能够dlsym
你自己的符号应该进入动态表)。
在我的Debian / Sid / x86-64系统上(使用gcc
版本4.8.2和libc6
版本2.17-93提供了我编译的-ldl
,kernel 3.11.6, binutils
package 2.23.90提供的ld
),执行./ds
给出了预期的输出:
% ./ds hello world
乃至:
% ltrace ./ds __libc_start_main(0x4009b3, 1, 0x7fff1d0088b8, 0x400a50, 0x400ae0 <unfinished ...> dlopen(NULL, 1) = 0x7f1e06c9e1e8 dlsym(0x7f1e06c9e1e8, "hello") = 0x004009a0 puts("hello world"hello world ) = 12 dlclose(0x7f1e06c9e1e8) = 0 +++ exited (status 0) +++
除了Basile Starynkevitchs优秀的答案之外,我想指出的是,这不适用于C ++编译器。
首先,你会得到一个警告,因为buf定义为char *已经被弃用了。 你可以改为const char *。
其次,C ++不允许你把dlsym的结果赋值给fptr,因为它拒绝隐式地转换类型。 您必须明确地投入类型
void (*fptr) (void) = (void (*)())dlsym (hndl, buf);
要么
void (*fptr) (void) = reinterpret_cast<void (*)()>(dlsym (hndl, buf));
第三,C ++的不同命名方案给函数“hello”赋予不同的名称,所以dlsym不会找到它。 你需要声明为
extern "C" void hello () {...}
编译为Basile Starynkevitch说,但用C ++代替C:
% g++ -Wall -rdynamic ds.cpp -o ds -ldl % ./ds hello world