在C语言中是否有一种通用函数指针可以分配/转换到限制更严格的原型?
我需要在运行时动态链接库,并使用在C语言中是否有一种通用函数指针可以分配/转换到限制更严格的原型?,c,function-pointers,dynamic-linking,C,Function Pointers,Dynamic Linking,我需要在运行时动态链接库,并使用dlsym解析一系列函数。我的第一个想法是使用一个函数指针数组,通过利用表示符号名的char*的二级数组,可以轻松地对其进行迭代 但是,问题是并非所有函数都采用相同的参数。有没有办法在数组中使用泛型函数指针,但将其分配给限制性更强的函数指针原型?例如: 如果需要解决这些功能: int (*functionA)(int) char (*functionB)(char,int) 有可能做类似(伪ish…)的事情吗 连同 char FuncNameA[] = "fun
dlsym
解析一系列函数。我的第一个想法是使用一个函数指针数组,通过利用表示符号名的char*
的二级数组,可以轻松地对其进行迭代
但是,问题是并非所有函数都采用相同的参数。有没有办法在数组中使用泛型函数指针,但将其分配给限制性更强的函数指针原型?例如:
如果需要解决这些功能:
int (*functionA)(int)
char (*functionB)(char,int)
有可能做类似(伪ish…)的事情吗
连同
char FuncNameA[] = "functionA";
char FuncNameB[] = "functionB";
char *functionNames[2] = {FuncNameA, FuncNameB};
用于循环调用dlsym
进行符号解析
int i = 0;
for(; i<2; i++)
functionList[i] = dlsym(DL_OPEN_HANDLE, functionNames[i]);
inti=0;
对于(;i您可能应该将列表定义为void*functionList[2]
,因为dlsym
返回一个void*
。一旦您知道您拥有哪个函数,就可以将其转换为正确的类型
void *functionList[2];
...
int (*functionA)(int) = (int(*)(int))functionList[0];
char (*functionB)(char,int) = (char(*)(char, int))functionList[1];
C标准保证任何对象指针类型都可以转换为void*
,然后再转换回来,而不会丢失信息(这意味着重新转换的指针将与原始指针进行比较)
函数指针有一个不同的保证:任何函数指针都可以转换为任何其他函数指针类型,然后再转换回来,而不会丢失信息
(对于函数指针和对象指针之间的转换,或者更具体地说函数指针和void*
之间的转换,没有任何保证。例如,一个实现可以使void*
64位和函数指针128位。)
例如,您可以使用void(*)(void)
作为通用函数指针类型:
typedef void (*funcptr)(void);
在执行调用之前,必须转换回原始指针类型,以避免未定义的行为
另一方面,您使用的是dlsym()
,它返回一个void*
。我的理解是,POSIX保证dlsym()
返回的void*
(如果name
参数命名一个函数)可以转换为函数指针,该指针可用于调用函数。如果您只关心其地址由dlsym()
返回的函数,则可以使用void*
(作为C标准的扩展,POSIX先前保证函数指针可以转换为void*
,然后再转换回来。这一保证后来被取消。多亏Jonathan Leffler指出了这一点。)
在任何情况下,使用函数指针存储函数的地址可能会使代码更清晰。dlsym
返回类型为void*
的数据指针,但POSIX保证可以将其转换为适当类型的函数指针:
支持XSI扩展[…]的实现要求类型为void*
的对象可以包含指向函数的指针。但是,将指向函数的指针转换为指向另一数据类型的指针(除了void*
)的结果仍然没有定义
自POSIX版本7以来,所有实现(不仅仅是XSI)都需要支持转换
由于通过直接转换从void*
指针到函数指针的转换可能会导致编译器警告,旧版本的POSIX建议通过别名执行转换:
int (*fptr)(int);
*(void **)(&fptr) = dlsym(handle, "my_function");
在当前版本中,建议更改为:
int (*fptr)(int);
fptr = (int (*)(int))dlsym(handle, "my_function");
@edtheprogrammerguy,我不知道。如果可能的话,我想它会像void*(*func)(void*,…)
,或类似内容。@edtheprogrammerguy:void*
可能会工作,但C标准不能保证。所有对象指针类型都可以转换为void*
,然后再转换回来,而不会丢失信息,但无法保证将函数指针类型转换为void*
。这是一个非常微妙的领域POSIX规范最近发生了变化。有关POSIX对这种情况的看法,请参阅。相关问题:。我想这就是我的想法,尽管出于某种原因,这是倒退的。谢谢!天哪,前一种语法很难看。后一种语法实际上是可读的;我不知道如何解释前一种语法。@sherrelbc它的别名fptr
,带有 void*
指针,方法是将指向fptr
的指针转换为指向void的指针,取消引用它,然后分配给结果。正如您所说,它很难看;但您可能会在相对较新的代码中看到它。遗憾的是,尽管它过去是,但现在不再是了。第节提供了直到POSIX 1003.1:2008的保证,但是在POSIX 1003.1:2013中删除了该小节。有关详细信息,请参见(也在对问题的评论中提到)。坦率地说,我不确定我们现在得到的比以前更好。@JonathanLeffler:所以POSIX仍然保证dlsym()
返回的void*
可以转换为函数指针(如果name
参数命名一个函数),但不能保证任意函数指针可以转换为void*
,然后再转换回来;对吗?AFAICT,是的。这非常奇怪,但是…谁说标准必须是合理的?回答很好。如果你把首先,“任何函数指针都可以转换为任何其他函数指针类型,然后再转换回来,而不会丢失信息”,然后才说不能保证函数指针可以转换为void*
并返回。记住-答案是“认知漏斗”“,但有些人很匆忙,略读,或者只是不善于阅读,所以你想帮助读者尽快、清楚地找到答案,然后再详细阐述。@KeithThompson Cool,th
int (*fptr)(int);
fptr = (int (*)(int))dlsym(handle, "my_function");