Nicky_AC Nicky_AC
关注数: 1 粉丝数: 16 发帖数: 501 关注贴吧数: 0
C++ "On The Fly" Code Compilation 许多带有前台(用户图形界面或终端界面)的数值计算程序往往需要完成这样的功能: 让用户输入一个表达式, 然后程序解析这个表达式并且求解(例如求零点, 不动点等等). 用户的输入可以是多种形式, 不过最为简单的是字符串形式. 例如 D(exp(cos(x)*x),x) + int(x*sin(x),x,0,1) 最常见的做法是构建一棵表达式二叉树并按照符号运算的规则进行求解. 这往往需要一个求解器(Evaluator)解析整个二叉树才能计算出一个表达式的值. 如果该表达式只需求解一次 (就像shell下的计算器程序一样), 那么其效率不成问题. 但如果该表达式需要求解许多次 (例如求一个映射的不动点) 就需要来回地迭代这个表达式直到满足指定条件 (例如两次求值的结果小于一个允差值). 缓慢的二叉树式求值会非常浪费时间. 那么我们是否可以在运行时"编译"给定的字符串呢? 我们申请一块堆内存, 把一个输入字符串转换为对应的机器码, 并写入这块内存中. 接下来我们只需要一个函数指针指向我们生成的机器码的入口点就可以执行这段代码了. 如果是在受虚拟保护的系统下运行则需要一个Unprotect操作, 在Win32下可能是这样: DWORD dwOldProtect;        VirtualProtect((LPVOID)crazy_code, sizeof(crazy_code),PAGE_EXECUTE_READWRITE, &dwOldProtect); 接下来我们就可以让机器直接跑原生机器代码, 而无需通过二叉树解析器来求值了. 是否有这样的库能够实现这一功能(这样的库就相当于一个轻量级编译器了)? P.S. 该想法源于Mathematica中的一个功能: CompiledFunction 作为一个符号运算工具, Mathematica往往运行得非常慢, 不过如果你需要一个高性能的纯数值函数的话则可以将其编译为CompiledFunction, 这样一来该函数会跑得和C代码一样快, 代价是只能接受Machine Number. 例如: cf = Compile[{{x,Real_}}, Sin[x_] + x^2 -1/(1+x)] cf就是一个编译过的函数. 接下来用机器数求cf在pi上的值: cf[3.14159] 得到 9.62815
1 下一页