我写了一个程序来自我解决
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);
}
但我得到“分段错误”错误 我使用.so库测试了这个程序,它可以工作,但不能让它自己工作
答案 0 :(得分:7)
您需要编码:
// 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
&amp;成功。 dlsym
在那里运行,并在失败时使用dlerror
。
并使用
编译上述ds.c
文件
gcc -std=c99 -Wall -rdynamic ds.c -o ds -ldl
不要忘记-Wall
获取所有警告和-rdynamic
标记(能够dlsym
您自己的符号,这些符号应该进入动态表格。)
在我的Debian / Sid / x86-64系统上(gcc
版本4.8.2和libc6
版本2.17-93提供-ldl
,内核3.11.6由我编译,binutils
包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) +++
答案 1 :(得分: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