简体   繁体   English

函数,名称和参数的数组

[英]array of functions, names, and arguments

I'm trying to use function that input (from file) - by they names. 我正在尝试使用输入(来自文件)的功能-由他们命名。

For example - In the file I wrote 例如-在我写的文件中

     functionOne(1,2)

I successed to separate the function name and his arguments to different array - now I have: 我成功地将函数名称和他的参数分隔到不同的数组中-现在我有了:

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

But, now I stuck - how I can use it? 但是,现在我卡住了-如何使用它? I tried to make an array of pointers to the functions, but Have not idea how to use it. 我试图制作一个指向函数的指针数组,但不知道如何使用它。 Any suggestion? 有什么建议吗? Thanks 谢谢

C doesn't have introspection . C没有内省 It's not possible, during runtime, to get or call a function from a string. 在运行时,无法从字符串获取或调用函数。

There are workarounds though. 虽然有解决方法。 For example you can create a table containing the name of the function and a pointer to the function. 例如,您可以创建一个包含函数名称和函数指针的表。 Then you can search this table to find the function to call. 然后,您可以搜索此表以找到要调用的函数。

Perhaps something like 也许像

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

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

To make it more generic, when you have many functions taking different amount of arguments, it's a little harder. 为了使它更通用,当您有许多函数采用不同数量的参数时,要难一些。 Then you could instead of passing arguments like normal, pass an array containing the arguments: 然后,您可以像传递普通的参数那样,传递包含参数的数组:

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

Modify the function pointer in the structure accordingly. 相应地在结构中修改函数指针。

If the types of arguments differ as well, then you could use structures with a type-tag and a union for the values. 如果参数的类型也不同,则可以使用带有类型标签和值的并集的结构。

You can't do the thing you want in C. The closest you can do is, keep an array of function pointers which will be pointing towars the respective functions. 您无法在C语言中执行所需的操作。最接近的操作是,保留一个将指向各个函数的函数指针数组。 Also keep a array of strings which is exactly as per the same index as that of other array. 还要保留一个字符串数组,该字符串与其他数组的索引完全相同。 Now whenever you get a function name - you just parse it, compare and get the appropriate function pointer based on the index of the matched string. 现在,只要获得函数名称,就可以对其进行解析,比较,并根据匹配的字符串的索引获取适当的函数指针。

How to send the arguemnts - well to do that I would say you go about this - when you know which function you will have to call, you parse the arguments from the file itself (You will know that this function will take 2 arguemnts - so you will get the line and parse it to int and double as it is expected and then you will call it accordingly). 如何发送辩论文件-很好地做到这一点,我会说这件事-当您知道必须调用哪个函数时,就可以从文件本身中解析参数(您将知道此函数将花费2个辩论文本-因此您将获得该行并将其解析为int ,并按预期将其double ,然后您将对其进行相应调用)。

In general, you cannot do what you want in portable C11 (read n1570 ), as explained by others: function names are a compile-time thing and are unknown at execution time. 通常, 您无法在便携式 C11 (读取n1570 )中做您想做的 事情 ,正如其他人所解释的: 函数名是编译时的事情 ,在执行时是未知的。 The C programming language doesn't have reflection and/or introspection . C编程语言没有反射和/或内省 BTW, a function might even "disappear" during optimized compilation (so don't "practically" exist at runtime, but your program behaves as-if that function exists), in the sense that it has been inlined or removed from the executable . 顺便说一句,在优化编译过程中,某个函数甚至可能“消失”(因此在运行时不“实际”存在,但是您的程序的行为就好像该函数存在一样),因为它已被内联或从可执行文件中删除。 However, C has function pointers (whose type describes the signature of the indirectly called function); 但是,C具有函数指针 (其类型描述了间接调用的函数的签名)。 practically speaking, they point to machine code . 实际上,它们指向机器代码


But if you code an application program on an x86-64 computer running eg Linux, you might sometimes have some workarounds, using some "dirty" tricks, specific to that operating system and instruction set architecture : 但是,如果您在运行例如Linux的x86-64计算机上编写应用程序代码,则有时可能使用一些“肮脏”的技巧来解决某些问题,这些技巧专门针对该操作系统指令集体系结构

  • given some string like "functionOne" (practically, of type const char* ), you could get a function pointer to it (eg the functionOne , provided it has extern linkage ) -thru dynamic linking facilities- using dlopen(3) with a NULL path, then dlsym(3) . 给定像"functionOne" (实际上是const char*类型)这样的字符串 ,您可以获得指向它的函数指针(例如functionOne ,只要它具有外部链接 )-通过动态链接工具-使用带有NULL dlopen(3)路径,然后是dlsym(3) BTW the reverse mapping (from addresses to names) is available thru dladdr(3) . 顺便说一句,反向映射(从地址到名称)可通过dladdr(3)获得

  • given a function pointer (or actually any valid address in your virtual address space pointing inside some executable code segment ), you could call it indirectly if the signature of that function is known at compile time (it is given in the type of that function pointer). 给定一个函数指针 (或者实际上是虚拟地址空间中指向某个可执行 代码段内的任何有效地址),如果在编译时已知该函数的签名,则可以间接调用它(以该函数指针的类型给出) )。

  • if you want to call an arbitrary function with arbitrary signature and arbitrary arguments only known at run-time , you might use the libffi . 如果要使用仅在运行时才知道的具有任意签名和任意参数的任意函数,则可以使用libffi It knows the ABI of your system. 它知道您系统的ABI

  • a possible trick is also to emit some temporary file /tmp/emittedcode.c containing C code (at runtime), fork a compilation process into a temporary plugin (eg gcc -Wall -O -shared -fPIC/tmp/emittedcode.c -o /tmp/emittedplugin.so ), and dynamically load that temporary plugin /tmp/emittedplugin.so with dlopen(3) . 一个可能的技巧是发出一些包含C代码的临时文件/tmp/emittedcode.c (在运行时),将编译过程派生到一个临时插件中(例如gcc -Wall -O -shared -fPIC/tmp/emittedcode.c -o /tmp/emittedplugin.so ),并使用dlopen(3) 动态加载该临时插件/tmp/emittedplugin.so Be sure to clean the mess (eg remove all temporary files, perhaps using atexit(3) ) at program termination. 确保在程序终止时清理混乱(例如,删除所有临时文件,也许使用atexit(3) )。

  • perhaps you want to generate some machine code at runtime; 也许您想在运行时生成一些机器代码; then consider also some JIT compiling library such as GCCJIT , LLVM , libjit , asmjit . 然后再考虑一些JIT编译库,例如GCCJITLLVMlibjitasmjit

If your PC is not running Linux, you might find equivalent stuff for your OS and computer. 如果您的PC未运行Linux,则可能会为您的OS和计算机找到同等的东西。 Read Operating Systems: Three Easy Pieces to learn more about OSes in general. 阅读操作系统:三篇简单的文章,以全面了解有关OS的更多信息。 Read the documentation of your particular OS (for Linux, read first the ALP or some newer book on Linux programming, then intro(2) , syscalls(2) , elf(5) and related pages). 阅读特定操作系统的文档(对于Linux,请先阅读ALP或有关Linux编程的新书,然后阅读intro(2)syscalls(2)elf(5)和相关页面)。


BTW, if you just want to call functions from your program (from names in some input file), you might instead build at initialization some hash table (or map , perhaps a red-black tree ) associating function names to function pointers, like suggested in this other answer. 顺便说一句,如果您只想从程序中调用函数(从某个输入文件中的名称),则可以在初始化时构建一些哈希表 (或map ,可能是一棵红黑树 ),将函数名与函数指针相关联,如建议的那样在这个其他的答案。

Maybe you want some homoiconic programming language having some eval primitive . 也许您想要具有某些eval原语的 homoiconic编程语言。 Look into Common Lisp. 查看Common Lisp。 Be aware of SBCL , it is compiling into dynamically generated machine code at most REPL interactions. 请注意SBCL ,它最多可以在REPL交互中编译为动态生成的机器代码。

Maybe you are writing some interpreter (that is often more difficult and time consuming than you think, read the Dragon Book ). 也许您正在编写一些解释器 (通常比您想象的要困难和耗时,请阅读《 龙书》 )。 Consider perhaps embedding and using an existing one, such as Guile or Lua . 考虑也许嵌入和使用现有的,例如GuileLua

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

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