我在一个驱动程序中声明了许多函数,并将指向函数的指针传递给具有节点格式的列表中的另一个驱动程序:
struct node
{
char def_prototype[256]; //example:(int (*)(wchar, int, int))
void *def_function;
};
Run Code Online (Sandbox Code Playgroud)
有没有办法来强制转换def_function在给出的原型def_prototype?
目前我正在使用简单的开关和strcmp,但我想尽可能概括它.
PS:我知道在void指针和函数指针之间进行转换是不安全的(如在SO的各个地方所提到的那样),但绝望的时候需要采取绝望的措施,我已经非常小心了.
编辑:
抱歉缺乏清晰度.我想实际调用函数(而不仅仅是强制转换它),在运行时根据提供的char []创建一个函数指针.
再次编辑:
由于我在内核级别(Windows驱动程序)工作,我无法访问太多资源,因此,我坚持我当前的实现(通过一些更改来杀死后门).感谢大家的帮助.
ISO-C不允许在函数和数据指针之间进行转换,即你应该使用a void (*)(void)来代替a void *来保存你的函数.
除此之外,YeenFei的断言是正确的,即没有通用的平台独立解决方案,这意味着你在C本身可以做的最好的事情是提供一个支持的签名列表.
您应该实现自己的编码方案,而不是使用普通的C原型.通常使用一个字符串,其中每个char表示一个函数参数(第一个是返回值); int (*)(wchar, int, int)例如,类型的函数可以具有签名"iwii".
然后可以使用bsearch()和轻松构建签名查找表strcmp().这是一个完整的例子:
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmp(const void *key, const void *element)
{
return strcmp(key, *(const char * const *)element);
}
static _Bool dispatch(const char *sig, void (*func)(void), void *retval, ...)
{
// supported signatures; must be ordered according to strcmp()
static const char * const SIGS[] = { "iii", "v", "vi" };
const char * const *match = bsearch(
sig, SIGS, sizeof SIGS / sizeof *SIGS, sizeof *SIGS, cmp);
if(!match) return 0;
va_list args;
va_start(args, retval);
switch(match - SIGS)
{
case 0: { // iii
int a1 = va_arg(args, int);
int a2 = va_arg(args, int);
int rv = ((int (*)(int, int))func)(a1, a2);
if(retval) memcpy(retval, &rv, sizeof rv);
break;
}
case 1: { // v
func();
break;
}
case 2: { // vi
int a1 = va_arg(args, int);
((void (*)(int))func)(a1);
break;
}
default:
assert(!"PANIC");
}
va_end(args);
return 1;
}
// example code:
static int add(int a, int b)
{
return a + b;
}
int main(void)
{
int sum;
dispatch("iii", (void (*)(void))add, &sum, 3, 4);
printf("%i", sum);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
523 次 |
| 最近记录: |