问题描述
我正在尝试在代码中使用dlopen()
和dlsym()
并使用gcc
进行编译.
I am trying to use dlopen()
and dlsym()
in my code and compile it with gcc
.
这是第一个文件.
/* main.c */
#include <dlfcn.h>
int main()
{
void *handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
void (*func)() = dlsym(handle, "func");
func();
}
return 0;
}
这是第二个文件.
/* foo.c */
#include <stdio.h>
void func()
{
printf("hello, world\n");
}
这是我编译和运行代码的方式.
Here is how I compile and run the code.
$ gcc -std=c99 -pedantic -Wall -Wextra -shared -fPIC -o foo.so foo.c
$ gcc -std=c99 -pedantic -Wall -Wextra -ldl -o main main.c
main.c: In function ‘main’:
main.c:10:26: warning: ISO C forbids initialization between function pointer and ‘void *’ [-Wpedantic]
void (*func)() = dlsym(handle, "func");
^
$ ./main
hello, world
如何摆脱警告?
类型转换无济于事.如果我尝试将dlsym()
的返回值类型转换为函数指针,则会收到此警告.
Type casting doesn't help. If I try to type cast the return value of dlsym()
into a function pointer, I get this warning instead.
main.c:10:26: warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]
void (*func)() = (void (*)()) dlsym(handle, "func");
^
什么会使编译器相信此代码是正确的?
What would convince the compiler that this code is fine?
推荐答案
如果您想获得正确的信息,请不要尝试解析函数的地址.而是从动态库中导出某种结构:
If you want to be pedantically correct, don't try to resolve the address of a function. Instead, export some kind of structure from the dynamic library:
struct export_vtable {
void (*helloworld)(void);
};
struct export_vtable exports = { func };
在呼叫者中
struct export_vtable {
void (*helloworld)(void);
};
int main() {
struct export_vtable* imports;
void *handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
imports = dlsym(handle, "exports");
if (imports) imports->helloworld();
}
return 0;
}
这种技术实际上很常见,不是为了可移植性-POSIX保证可以将函数指针与void *进行相互转换,但是因为它具有更大的灵活性.
This technique is actually quite common, not for portability -- POSIX guarantees that function pointers can be converted to and from void* -- but because it allows more flexibility.
这篇关于如何正确地将dlsym返回的指针分配给函数指针类型的变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!