简体   繁体   English

如果仅在运行时知道参数数目,如何调用函数指针

[英]How do I call a function pointer where number of arguments if only known at runtime

In c, consider this scenario. 在c中,请考虑这种情况。 I have an array of function pointers and I want to call each of them. 我有一个函数指针数组,我想分别调用它们。 I also have an array of integers telling me how many arguments each one takes. 我也有一个整数数组,告诉我每个参数接受多少个参数。 I thirdly have an array of the arguments that I want to call them with. 第三,我想调用它们的参数数组。 The following program is an example of a program that uses this: 以下程序是使用此程序的示例:

int foo(int a, int b, int c){
    return a+b+c;
}

int bar(int a, int b){
    return a+b;
}

int baz(int a){
    return a;
}

int qux(){
    return 0;
}


int main(){
    void *funcArray[4] = {foo, bar, baz, qux}; //an array of function pointers, all of which return ints but have different numbers of arguments
    int argArray[3+2+1+0] = {100,30,1,  20,7,  9}; //these are the arguments to the functions to be executed
    int numArgsArray[4] = {3,2,1,0}; //these are the numbers of arguments that each function takes in the funcArray array
    int nextArg = 0; //used to keep track of which argument goes to which function

    for (int i = 0; i<4; i++){
        int result;
        switch(numArgsArray[i]){
        case 0://if the function takes no args, just call it
            result = ((int(*)())funcArray[i])();
            break;
        case 1://if the function takes one arg, pass it the argument when calling it
            result = ((int(*)(int))funcArray[i])(argArray[nextArg]);
            nextArg += 1;
            break;
        case 2://if the function takes two arguments, pass it both when calling
            result = ((int(*)(int, int))funcArray[i])(argArray[nextArg], argArray[nextArg+1]);
            nextArg += 2;
            break;
        case 3://if the function takes three args, pass it all three when calling
            result = ((int(*)(int, int, int))funcArray[i])(argArray[nextArg], argArray[nextArg+1], argArray[nextArg+2]);
            nextArg += 3;
            break;
        }
        printf("%d\n", result);
    }

    return 0;
}

The above program works, and outputs: 131 27 9 0 This is the intented output. 上面的程序起作用,并输出:131 27 9 0这是预期的输出。 The problem is that I need to have a case in the switch statement for each number of arguments that I want to support. 问题是,我需要在switch语句中为每个要支持的参数数目添加一个大小写。 So my question is: is there an easier way to do this that isn't so ugly and will work with any number of arguments? 所以我的问题是:有没有一种更简单的方法来做到这一点,而且它并不那么丑陋,并且可以处理任意数量的参数?

If possible, instead of separate functions for each number of parameters, write a function that takes an array of int s instead with a count, or even consider using <stdarg.h> but you'll still need some kind of sentinel or count. 如果可能的话,代替编写用于每个参数数量的单独函数,而是编写一个使用int数组代替计数的函数,甚至考虑使用<stdarg.h>但您仍然需要某种哨兵或计数。

Otherwise, you're into non-portable implementation-specified behaviours not guaranteed by the language standard itself.... 否则,您将陷入语言标准本身无法保证的非便携式实现特定行为。

With some calling conventions (eg read here for x86 examples , you can call the function with extra arguments and they'll sit ignored in registers or on the stack while the ones of interest are used correctly, then be discarded as the original stack pointer is restored. On other architectures, the amount by which the stack pointer is adjusted when the function returns relates to the number of function parameters, so the above approach will crash. If you want to read up on your compiler/system's conventions and have a non-portable solution, that's an option. 使用某些调用约定(例如, 在此处阅读x86示例) ,可以使用附加参数来调用该函数,而在正确使用相关的参数时,它们将在寄存器或堆栈中被忽略,然后由于原始堆栈指针被丢弃而被丢弃。在其他体系结构上,函数返回时调整堆栈指针的数量与函数参数的数量有关,因此上述方法将崩溃:如果您想阅读编译器/系统的约定并且有一个非-便携式解决方案,这是一个选择。

Otherwise, again depending on your calling conventions, you may be able to use assembly language to push some number of arguments on the stack before calling the function. 否则,再次取决于您的调用约定,您可能能够在调用函数之前使用汇编语言在堆栈上推送一些参数。 I've seen questions with code doing that on stackoverflow, but it might take some digging to find one. 我已经在stackoverflow上看到过用代码执行此操作的问题,但是可能要花一些时间才能找到一个。 Still, you'd want one corresponding to the calling convention you're using. 不过,您仍需要一个与您所使用的调用约定相对应的。

This can be improved slightly: 可以稍微改善一下:

typedef int (*FuncP)();    // function returning int and taking unspecified arguments
FuncP func_array[4] = { foo, bar, baz, qux };

// ...

// cast unnecessary
case 1:
    result = funcArray[i](arg1);

If you call a function with the wrong number or type of arguments then it causes undefined behaviour, but so long as you keep track of your argument counts specifically like you actually do in your code, then it's well-defined. 如果您使用错误的数量或类型的参数调用函数,则会导致未定义的行为,但是,只要像您在代码中实际那样跟踪参数的数量,就可以很好地定义它。

There's no simpler way that retains portability and also retains the functions as they are. 没有比这更简单的方法来保留可移植性和功能。 On some systems you'd get away with passing extra dummy arguments. 在某些系统上,您会通过传递额外的伪参数来避免麻烦。

Of course you could rewrite the functions to take a structure which contains a variable-length argument list as TonyD suggests. 当然,您可以重写函数,以采用包含TonyD建议的可变长度参数列表的结构。 You could also write thunks for each function that take a fixed argument list, but that would be just as much work as your switch table. 您还可以为每个带有固定参数列表的函数编写thunk,但这将与switch表一样多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否可以使用函数指针调用函数,该函数指针具有仅在运行时知道的参数的数量和类型 - Is it possible to call a function using a function pointer with number and type of arguments known only at runtime 如何使用运行时已知的类型调用 function - How to call a function with types known at runtime 关于 function 指针采用任意数量的 arguments,如何使 C 编译器安静下来? - How do I quiet the C compiler about a function pointer takes any number of arguments? 如何使用指针变量调用函数? - How do I call a function with pointer variable? 如何为接受函数指针的函数提供参数 - How do I give arguments to a function that accepts function pointer 如何将参数绑定到 C 函数指针? - How do I bind arguments to a C function pointer? 我如何使用dlsym()调用函数,但我不知道参数的数量但不知道函数的类型,也不知道函数的返回类型? - How do I invoke a function using dlsym() where I know the number of arguments but not the type and neither the return type of the function? 如何在C中调用(不定义)具有可变数量参数的函数? - How can I call (not define) a function with a variable number of arguments in C? 如何调用前面有指针的函数 - How do I call function that has pointer before it 如何调用返回空指针的函数? - How do I call a function that returns a void pointer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM