要求:对于某个项目,我们有独特的要求。该应用程序支持一种表达式语言,允许用户定义自己的复杂表达式,这些表达式可以在运行时进行评估(每秒数百次),并且需要在机器级别执行以提高性能。
工作:我们的表达式解析器将脚本完美地转换为相应的汇编语言例程。我们通过静态链接使用我们的C测试程序生成的目标文件来检查它们,它们产生了正确的结果。 由于客户端可以随时更改脚本,因此我们的程序(在运行时)检测到更改,调用生成相应汇编例程的解析器。然后我们从后端调用汇编程序来创建目标代码。
问题
如何从C ++程序动态调用此程序集例程 (装载程序)?
我们不应该调用C ++编译器将它与加载器链接起来,因为加载器已经有其他子程序在运行,我们不能关闭加载器,重新编译然后执行新的加载程序。
我尝试在线搜索解决方案,但每次使用.NET程序集动态调用时都会出现结果。我们的应用程序与.NET无关。
答案 0 :(得分:2)
正如评论已经提出的那样,LoadLibrary
(Windows)和dlopen
(Linux / POSIX)是迄今为止最简单的解决方案。这些专门用于动态加载代码。同样重要的是,它们都允许卸载,然后有一些函数可以按名称获取函数入口点。
答案 1 :(得分:2)
你可以动态地做到这一点。我将以linux案例为例。由于您的解析器工作正常并生成机器代码,您应该能够为Windows生成.so(对于linux)或.dll。
接下来,将库加载为
handle = dlopen(so_file_name, RTLD_LAZY);
接下来获取函数指针
func = dlsym(handle, "function_name");
然后你应该能够以func()
的形式执行它您需要尝试的一件事(如果您没有得到理想的结果)是关闭并打开so文件或dll文件(您只需要在需要时执行,否则可能会降低性能)
答案 2 :(得分:2)
听起来你可以生成正确的字节码。因此,您可以确保生成与位置无关的代码,将其写入可执行的内存块,然后在代码上调用或创建线程。最简单的方法就是将指针编写到你编写代码的内存的基础作为函数指针,然后调用它。
如果您编写字节码以避免引用不同的部分,而是从其加载的基数中引用偏移量,那么就可以加载'代码就像将代码写入可执行内存一样简单。一旦开始执行,你就可以调用/ pop / jmp来查找代码的基础。
相反,也许最简单的解决方案是将代码编写为函数期望参数,这样就可以将代码的基础和任何其他参数传递给它,就像使用任何其他函数一样,只要为函数指针使用正确的typedef,生成的程序集就能正确处理参数。只要您避免创建绝对跳转或绝对地址的数据引用,您就不会有任何问题。
答案 3 :(得分:1)
为时已晚,但我认为这会帮助别人。 如果要动态执行一段代码,可以为此创建一个解释器。 将您的表达式编译为一些字节代码,然后编写解释器以执行此操作。
这是有关编写解释器的教程,但使用python。
https://ruslanspivak.com/lsbasi-part1/
您可以使用c / c ++编写它