我试图使用输入的函数(来自文件) - 按名称命名。
例如 - 在我写的文件中
functionOne(1,2)
我成功地将函数名称和他的参数分离到不同的数组 - 现在我有:
funcName[] = functioOne
funcArg[0] = 1
funcArg[1] = 2
但是,现在我卡住了 - 我怎么能用它?我试图创建一个指向函数的指针数组,但不知道如何使用它。有什么建议吗?感谢
答案 0 :(得分:2)
你无法在C中做你想做的事情。你可以做的最接近的是,保留一系列函数指针,它们将指向各自的功能。还要保留一个字符串数组,这与其他数组的索引完全相同。现在,无论何时获得函数名称 - 只需解析它,比较并根据匹配字符串的索引获取相应的函数指针。
如何发送arguemnts - 很好地做到这一点我会说你去做 - 当你知道你将要调用哪个函数时,你解析文件本身的参数(你会知道这个函数需要2 arguemnts - 所以你将获得该行并按预期将其解析为int
和double
,然后你会相应地调用它。)
答案 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-64和operating 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 compiling,GCCJIT,LLVM。
如果您的PC没有运行Linux,您可能会找到适合您的操作系统和计算机的东西。阅读libjit以了解有关操作系统的更多信息。阅读特定操作系统的文档(对于Linux,请先阅读asmjit或有关Linux编程的新书,然后阅读Operating Systems: Three Easy Pieces,ALP,intro(2)和相关页面。
顺便说一句,如果您只是想从程序中调用函数(来自某些输入文件中的名称),您可能会在初始化时构建一些syscalls(2)(或elf(5),也许是{{3} })将函数名称与函数指针相关联,如hash table其他答案中所述。
也许你想要一些map编程语言有一些red-black tree。看看Common Lisp。请注意this,它会在大多数homoiconic次互动中汇编为动态生成的机器代码。
也许你正在写一些eval
primitive(这通常比你想象的更困难和耗时,请阅读SBCL)。考虑嵌入和使用现有的,例如REPL或interpreter。