根据编译时生成的函数数,在运行时用c++生成函数
build function at runtime c++ from number of functions that built at compilation
我正在创建首先解析代码的脚本语言然后将函数(执行代码)复制到一个缓冲区\内存中作为解析的代码。
有没有一种方法可以将函数的二进制代码复制到缓冲区,然后执行整个缓冲区?我需要同时执行所有的功能以获得更好的性能。
为了更好地理解我的问题,我想做这样的事情:
#include <vector>
using namespace std;
class RuntimeFunction; //The buffer to my runtime function
enum ByteCodeType {
Return,
None
};
class ByteCode {
ByteCodeType type;
}
void ReturnRuntime() {
return;
}
RuntimeFunction GetExecutableData(vector<ByteCode> function) {
RuntimeFunction runtimeFunction=RuntimeFunction(sizeof(int)); //Returns int
for (int i = 0 ; i < function.size() ; i++ ) {
#define CurrentByteCode function[i]
if (CurrentByteCode.Type==Return) {
runtimeFunction.Append(&ReturnRuntime);
} //etc.
#undef
}
return runtimeFunction;
}
void* CallFunc(RuntimeFunction runtimeFunction,vector<void*> custom_parameters) {
for (int i=custom_parameters-1;i>=0;--i) { //Invert parameters loop
__asm {
push custom_parameters[i]
}
}
__asm {
call runtimeFunction.pHandle
}
}
有很多方法可以做到这一点,具体取决于您希望在运行时生成代码的深度,但一种相对简单的方法是使用线程代码和线程代码解释器。
基本上,线程代码由一个函数指针数组组成,解释器通过该数组调用每个指向函数的指针。棘手的部分是,通常每个函数都会返回数组元素的地址,其中包含指向要调用的下一个函数的指针,这使您可以在解释器中实现分支和调用等功能
通常你会使用这样的东西:
typedef void *(*tc_func_t)(void *, runtime_state_t *);
void *interp(tc_func_t **entry, runtime_state_t *state) {
tc_func_t *pc = *entry;
while (pc) pc = (*pc)(pc+1, state);
return entry+1;
}
这就是整个翻译。runtime_state_t
是某种数据结构,包含一些运行时状态(通常是一个或多个堆栈)。您可以通过创建一个tc_func_t
函数指针数组并用函数指针(可能还有数据)填充它们来调用它,以空指针结束,然后用包含数组开头的变量的地址来调用interp
。所以你可能会有这样的东西:
void *add(tc_func_t *pc, runtime_state_t *state) {
int v1 = state->data.pop();
int v2 = state->data.pop();
state->data.push(v1 + v2);
return pc; }
void *push_int(tc_func_t *pc, runtime_state_t *state) {
state->data.push((int)*pc);
return pc+1; }
void *print(tc_func_t *pc, runtime_state_t *state) {
cout << state->data.pop();
return pc; }
tc_func_t program[] = {
(tc_func_t)push_int,
(tc_func_t)2,
(tc_func_t)push_int,
(tc_func_t)2,
(tc_func_t)add,
(tc_func_t)print,
0
};
void run_prgram() {
runtime_state_t state;
tc_func_t *entry = program;
interp(&entry, &state);
}
调用run_program
运行添加2+2并打印结果的小程序。
现在,您可能会对interp
的稍微奇怪的调用设置感到困惑,entry
参数上有一个额外的间接级别。这样,您就可以将interp
本身用作线程代码数组中的函数,后面跟着指向另一个数组的指针,它将执行线程代码调用。
编辑
像这样的线程代码最大的问题与性能有关——线程编码解释器对分支预测器极不友好,因此性能几乎锁定在每个分支预测失误恢复时间一个线程指令调用。
如果你想要更高的性能,你几乎必须进行完整的运行时代码生成。LLVM提供了一个很好的、独立于机器的接口来实现这一点,同时为通用平台提供了非常好的优化器,这些优化器将在运行时生成非常好的代码。
- 如何用参数值调用函数(仅在运行时已知)
- 函数在Windows或Linux上运行时表现不同
- 在运行时解析函数,而不是在编译C++解析函数
- 如何在 constexpr 函数中实现回退运行时
- 扩展类中的可选 vir 函数,测试它在运行时是否存在
- "main"函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)
- 运行时的动态函数解析
- 字符串函数在目标C++上运行时C++返回空
- 为什么在尝试测量函数返回所需的时间时,我的运行时编号是错误的?
- 这个递归函数有什么作用?运行时的复杂性是多少?
- 如何在函数运行时逐个显示列表项
- 在函数运行时停止 Wt C++函数
- C 构造函数运行时/编译时间
- 是否可以在析构函数运行时不销毁 obj
- 参数的可变数量函数运行时错误
- 具有变量参数的函数运行时错误
- C++析构函数运行时错误:无法munmap
- 如何在 MEX 函数运行时制作它 printf?
- C++回调函数运行时错误
- 类型缺失的模板函数(运行时未使用)函数