[英]array of functions, names, and arguments
我正在尝试使用输入(来自文件)的功能-由他们命名。
例如-在我写的文件中
functionOne(1,2)
我成功地将函数名称和他的参数分隔到不同的数组中-现在我有了:
funcName[] = functioOne
funcArg[0] = 1
funcArg[1] = 2
但是,现在我卡住了-如何使用它? 我试图制作一个指向函数的指针数组,但不知道如何使用它。 有什么建议吗? 谢谢
C没有内省 。 在运行时,无法从字符串获取或调用函数。
虽然有解决方法。 例如,您可以创建一个包含函数名称和函数指针的表。 然后,您可以搜索此表以找到要调用的函数。
也许像
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.
...
}
相应地在结构中修改函数指针。
如果参数的类型也不同,则可以使用带有类型标签和值的并集的结构。
您无法在C语言中执行所需的操作。最接近的操作是,保留一个将指向各个函数的函数指针数组。 还要保留一个字符串数组,该字符串与其他数组的索引完全相同。 现在,只要获得函数名称,就可以对其进行解析,比较,并根据匹配的字符串的索引获取适当的函数指针。
如何发送辩论文件-很好地做到这一点,我会说这件事-当您知道必须调用哪个函数时,就可以从文件本身中解析参数(您将知道此函数将花费2个辩论文本-因此您将获得该行并将其解析为int
,并按预期将其double
,然后您将对其进行相应调用)。
通常, 您无法在便携式 C11 (读取n1570 )中做您想做的 事情 ,正如其他人所解释的: 函数名是编译时的事情 ,在执行时是未知的。 C编程语言没有反射和/或内省 。 顺便说一句,在优化编译过程中,某个函数甚至可能“消失”(因此在运行时不“实际”存在,但是您的程序的行为就好像该函数存在一样),因为它已被内联或从可执行文件中删除。 但是,C具有函数指针 (其类型描述了间接调用的函数的签名)。 实际上,它们指向机器代码 。
但是,如果您在运行例如Linux的x86-64计算机上编写应用程序代码,则有时可能会使用一些“肮脏”的技巧来解决某些问题,这些技巧专门针对该操作系统和指令集体系结构 :
给定像"functionOne"
(实际上是const char*
类型)这样的字符串 ,您可以获得指向它的函数指针(例如functionOne
,只要它具有外部链接 )-通过动态链接工具-使用带有NULL
dlopen(3)路径,然后是dlsym(3) 。 顺便说一句,反向映射(从地址到名称)可通过dladdr(3)获得 。
给定一个函数指针 (或者实际上是虚拟地址空间中指向某个可执行 代码段内的任何有效地址),如果在编译时已知该函数的签名,则可以间接调用它(以该函数指针的类型给出) )。
一个可能的技巧是发出一些包含C代码的临时文件/tmp/emittedcode.c
(在运行时),将编译过程派生到一个临时插件中(例如gcc -Wall -O -shared -fPIC/tmp/emittedcode.c -o /tmp/emittedplugin.so
),并使用dlopen(3) 动态加载该临时插件/tmp/emittedplugin.so
。 确保在程序终止时清理混乱(例如,删除所有临时文件,也许使用atexit(3) )。
也许您想在运行时生成一些机器代码; 然后再考虑一些JIT编译库,例如GCCJIT , LLVM , libjit , asmjit 。
如果您的PC未运行Linux,则可能会为您的OS和计算机找到同等的东西。 阅读操作系统:三篇简单的文章,以全面了解有关OS的更多信息。 阅读特定操作系统的文档(对于Linux,请先阅读ALP或有关Linux编程的新书,然后阅读intro(2) , syscalls(2) , elf(5)和相关页面)。
顺便说一句,如果您只想从程序中调用函数(从某个输入文件中的名称),则可以在初始化时构建一些哈希表 (或map ,可能是一棵红黑树 ),将函数名与函数指针相关联,如建议的那样在这个其他的答案。
也许您想要具有某些eval
原语的 homoiconic编程语言。 查看Common Lisp。 请注意SBCL ,它最多可以在REPL交互中编译为动态生成的机器代码。
也许您正在编写一些解释器 (通常比您想象的要困难和耗时,请阅读《 龙书》 )。 考虑也许嵌入和使用现有的,例如Guile或Lua 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.