繁体   English   中英

函数,名称和参数的数组

[英]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)获得

  • 给定一个函数指针 (或者实际上是虚拟地址空间中指向某个可执行 代码段内的任何有效地址),如果在编译时已知该函数的签名,则可以间接调用它(以该函数指针的类型给出) )。

  • 如果要使用仅在运行时才知道的具有任意签名和任意参数的任意函数,则可以使用libffi 它知道您系统的ABI

  • 一个可能的技巧是发出一些包含C代码的临时文件/tmp/emittedcode.c (在运行时),将编译过程派生到一个临时插件中(例如gcc -Wall -O -shared -fPIC/tmp/emittedcode.c -o /tmp/emittedplugin.so ),并使用dlopen(3) 动态加载该临时插件/tmp/emittedplugin.so 确保在程序终止时清理混乱(例如,删除所有临时文件,也许使用atexit(3) )。

  • 也许您想在运行时生成一些机器代码; 然后再考虑一些JIT编译库,例如GCCJITLLVMlibjitasmjit

如果您的PC未运行Linux,则可能会为您的OS和计算机找到同等的东西。 阅读操作系统:三篇简单的文章,以全面了解有关OS的更多信息。 阅读特定操作系统的文档(对于Linux,请先阅读ALP或有关Linux编程的新书,然后阅读intro(2)syscalls(2)elf(5)和相关页面)。


顺便说一句,如果您只想从程序中调用函数(从某个输入文件中的名称),则可以在初始化时构建一些哈希表 (或map ,可能是一棵红黑树 ),将函数名与函数指针相关联,如建议的那样在这个其他的答案。

也许您想要具有某些eval原语的 homoiconic编程语言。 查看Common Lisp。 请注意SBCL ,它最多可以在REPL交互中编译为动态生成的机器代码。

也许您正在编写一些解释器 (通常比您想象的要困难和耗时,请阅读《 龙书》 )。 考虑也许嵌入和使用现有的,例如GuileLua

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM