【发布时间】:2019-11-11 17:36:37
【问题描述】:
我读到了eval in C,如果你编写一个 C 字符串解析器/求值器,你可以将它映射到你的主 C 程序中的特定函数。但据我所知,它实际上并没有将它放入可执行内存中,就像JIT compiler 似乎所做的那样。我不完全了解 JIT 编译器(我从未做过),但我明白了要点。
所以我想知道的是,您是否可以在 C 中创建某种 JIT 编译器,而无需做太多的解析 C 字符串和转换为 AST 之类的工作。基本上,你能不能像在 JavaScript 中那样动态地创建一个函数(在 C 中),使得该函数与任何其他 C 函数完全相同(即它直接编译成可执行的机器代码程序的可执行部分之类的东西)。
如果无法做到这一点,第二种方法是动态加载 C 导入/文件/模块。因此,您分离出一个告诉 clang 编译器编译一些库函数的进程,完成后,在不停止当前程序的情况下,它将新程序库链接/附加到自身,因此可以执行代码 那样。
如果这是不可能的,也许一个选项是简单地在后台重新编译程序,然后将当前程序与从头启动的新程序交换。不过那只是非常原始。
试图弄清楚您在 C 中是否有一些用于您自己的自定义函数数据类型的结构,然后如何以最优化的方式在 C 中执行该函数。
【问题讨论】:
-
您链接到的问题中的current top answer 似乎显示了一种编译C 代码并将结果链接到当前程序的方法。这正是您在第三段中所要求的。当然,在典型的通用系统中,完全可以在主内存而不是磁盘或其他存储中编译代码并执行该代码,但这当然比调用现有的编译器和链接器要多得多的工作。需要详细了解目标系统上的 ABI。...
-
... 在实践中,调用编译器和链接器本质上是不值得的,除非作为一个学术练习,而且在内存中做这一切更不用说。当然,“如果您在 C 中为您自己的自定义函数数据类型提供了一些结构”,那么以这种方式执行函数将不是“最优化的方式”。
-
dlopen(Unix) 或LoadLibrary(Windows) 是否适合您的需求?他们确实将编译后的二进制文件加载到可执行内存中。 -
我曾经写过一个成熟的 C 解释器来完成所有这些工作。这是一个有趣的挑战——困难,但可行。今天既困难又容易,因为事情变得更加复杂,尽管现在有一些库可以完成一些我必须手动完成的事情。
-
(续) (1) 如果您想加载并动态链接到
.so文件中的代码,这就是dlopen的用途。 (2) 如果您想跳转到已加载的任意代码(传递任意参数),这就是 libffi 的用途。 (3) 如果您想加载并动态链接到单个.o文件(或旧式静态.a库),我不知道这样做的好方法,我很想尘埃落定关闭我的旧自制动态链接器,并教它现代目标文件格式。