Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C语言中是否有一种通用函数指针可以分配/转换到限制更严格的原型?_C_Function Pointers_Dynamic Linking - Fatal编程技术网

在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");