函数,名称和参数数组

时间:2018-01-20 15:01:34

标签: c

我试图使用输入的函数(来自文件) - 按名称命名。

例如 - 在我写的文件中

     functionOne(1,2)

我成功地将函数名称和他的参数分离到不同的数组 - 现在我有:

    funcName[] = functioOne
    funcArg[0] = 1
    funcArg[1] = 2

但是,现在我卡住了 - 我怎么能用它?我试图创建一个指向函数的指针数组,但不知道如何使用它。有什么建议吗?感谢

3 个答案:

答案 0 :(得分:2)

你无法在C中做你想做的事情。你可以做的最接近的是,保留一系列函数指针,它们将指向各自的功能。还要保留一个字符串数组,这与其他数组的索引完全相同。现在,无论何时获得函数名称 - 只需解析它,比较并根据匹配字符串的索引获取相应的函数指针。

如何发送arguemnts - 很好地做到这一点我会说你去做 - 当你知道你将要调用哪个函数时,你解析文件本身的参数(你会知道这个函数需要2 arguemnts - 所以你将获得该行并按预期将其解析为intdouble,然后你会相应地调用它。)

答案 1 :(得分:2)

C没有introspection。在运行期间,从字符串中获取或调用函数是不可能的。

但是有一些解决方法。例如,您可以创建一个包含函数名称和指向函数的指针的表。然后,您可以搜索此表以查找要调用的函数。

也许像

void functionOne(int arg1, int arg2)
{
    ...
}

struct
{
    char *name;
    void (*function)(int, int);
} functions[] = {
    { "funcitonOne", &functionOne },
};

为了使它更通用,当你有许多函数使用不同数量的参数时,它会更难一点。然后你可以代替像普通一样传递参数,传递一个包含参数的数组:

void functionOne(int *arguments)
{
    // arguments[0] is the first arguments, etc.
    ...
}

相应地修改结构中的函数指针。

如果参数类型也不同,那么您可以使用带有type-tag和union的结构作为值。

答案 2 :(得分:0)

一般来说,你不能在 portable C11 (阅读n1570)中做你想做的事,正如其他人所解释的那样:函数名称是编译时事物并且在执行时未知。 C编程语言没有reflection和/或introspection。顺便说一句,一个功能甚至可能会消失"在optimized compilation期间(所以不要#34;实际上"在运行时存在,但你的程序行为as-if该函数存在),从某种意义上说它是{{3} }或从inlined中删除。但是,C有executable(其类型描述了间接调用函数的签名);实际上,他们指的是function pointers

但是,如果您在machine code计算机上对应用程序进行编码,例如Linux,您可能有时有一些解决方法,使用一些"脏"特定于x86-64operating system的技巧:

  • 给出一些 string ,如"functionOne"(实际上,类型为const char*),你可以得到一个函数指针(例如functionOne ,如果它具有外部instruction set architecture) - 动态链接设施 - 使用linkage使用NULL路径,然后dlopen(3)。顺便说一句,反向映射(从地址到名称)可通过dlsym(3)获得。

  • dladdr(3) {或实际上任何有效地址function pointer指向某个可执行文件 virtual address space) ,如果在编译时已知该函数的签名,则可以间接调用它(它以该函数指针的类型给出)。

  • 如果您想使用任意签名和仅在运行时知道的任意参数调用任意函数,您可以使用code segment 。它知道您系统的libffi

  • 一个可能的技巧是发出一些包含C代码的临时文件/tmp/emittedcode.c(在运行时),将编译过程分成一个临时插件(例如gcc -Wall -O -shared -fPIC/tmp/emittedcode.c -o /tmp/emittedplugin.so)和{{3带有ABI的临时插件/tmp/emittedplugin.so。务必在程序终止时清理混乱(例如,删除所有临时文件,可能使用dynamically load)。

  • 也许你想在运行时生成一些机器代码;然后还考虑一些dlopen(3)库,例如atexit(3)JIT compilingGCCJITLLVM

如果您的PC没有运行Linux,您可能会找到适合您的操作系统和计算机的东西。阅读libjit以了解有关操作系统的更多信息。阅读特定操作系统的文档(对于Linux,请先阅读asmjit或有关Linux编程的新书,然后阅读Operating Systems: Three Easy PiecesALPintro(2)和相关页面。

顺便说一句,如果您只是想从程序中调用函数(来自某些输入文件中的名称),您可能会在初始化时构建一些syscalls(2)(或elf(5),也许是{{3} })将函数名称与函数指针相关联,如hash table其他答案中所述。

也许你想要一些map编程语言有一些red-black tree。看看Common Lisp。请注意this,它会在大多数homoiconic次互动中汇编为动态生成的机器代码。

也许你正在写一些eval primitive(这通常比你想象的更困难和耗时,请阅读SBCL)。考虑嵌入和使用现有的,例如REPLinterpreter