我将宏定义为:
#define _call(func_name, __func_proto, ...) { \
void *_handle; \
int result = !CERR_V_SUCCESS; \
\
_handle = dlopen(_DLL_NAME,GLOBAL); \
if (_handle) { \
__func_proto = dlsym(dll_handle, func_name); \
if (__func_proto) { \
result = (*__func_proto)(__VA_ARGS__); \
} \
(void)dlclose(_handle); \
} \
return (result); \
}
我用不同的函数指针调用这个宏:
_call("download",_download,src,dst);
_call("upload",_upload,src,dst);
_call("test",_test,file);
并且函数指针定义为
int (*_download )(int *,int *);
int (*_upload)(int *,int*);
int (*_test)(int *,char*);
这会产生警告a value of type "void *" cannot be assigned to an entity of type "int (*)(int*,int*)"
。
如何解决此警告?
答案 0 :(得分:3)
Documentation of dlsym建议您在将其返回值指定给指针之前将函数指针强制转换为void*
:
*(void **)(&__func_proto) = dlsym(dll_handle, func_name);
原则在链接背后描述:
ISO C标准不要求指向函数的指针可以来回转换为指向数据的指针。实际上,ISO C标准不要求void *类型的对象可以保存指向函数的指针。但是,支持XSI扩展的实现确实需要void *类型的对象可以保存指向函数的指针。
请注意,如果尝试从void *指针到函数指针的转换,则需要符合ISO C标准的编译器生成警告:
fptr =(int(*)(int))dlsym(句柄," my_function");
答案 1 :(得分:1)
您需要添加强制转换,因为void *
不会自动转换为/从函数指针转换。事实上,假设函数指针可以表示为void *
,这是不可移植的。
当然,如果您使用的是具有dlopen()
和朋友的系统,则可以肯定地假设该平台支持此转换。
另外,每次调用整个dlopen()
/ dlsym()
/ dlclose()
舞听起来很奇怪,通常你会缓冲指针。