将脚本预编译到C ++应用程序内的对象中

时间:2021-01-02 00:29:58

I need to provide my users the ability to write mathematical computations into the program. I plan to have a simple text interface with a few buttons including those to validate the script grammar, save etc.

我需要为我的用户提供将数学计算写入程序的能力。我计划有一个带有几个按钮的简单文本界面,包括验证脚本语法,保存等的按钮。

Here's where it gets interesting. These functions the user is writing need to execute at multi-megabyte line speeds in a communications application. So I need the speed of a compiled language, but the usage of a script. A fully interpreted language just won't cut it.

这是有趣的地方。用户编写的这些功能需要在通信应用程序中以兆兆字节的速度执行。所以我需要编译语言的速度,但需要使用脚本。完全解释的语言不会削减它。

My idea is to precompile the saved user modules into objects at initialization of the C++ application. I could then use these objects to execute the code when called upon. Here are the workflows I have in mind:

我的想法是在C ++应用程序初始化时将保存的用户模块预编译为对象。然后,我可以在调用时使用这些对象来执行代码。以下是我的工作流程:

1) Testing(initial writing) of script: Write code in editor, save, compile into object (testing grammar), run with test I/O, Edit Code

1)脚本的测试(初始编写):在编辑器中编写代码,保存,编译成对象(测试语法),使用测试I / O运行,编辑代码

2) Use of Code (Normal operation of application): Load script from file, compile script into object, Run object code, Run object code, Run object code, etc.

2)Code的使用(应用程序的正常运行):从文件加载脚本,将脚本编译成对象,运行目标代码,运行目标代码,运行目标代码等。

I've looked into several off the shelf interpreters, but can't find what I'm looking for. I considered JAVA, as it is pretty fast, but I would need to load the JAVA virtual machine, which means passing objects between C and the virtual machine... The interface is the bottleneck here. I really need to create a native C++ object running C++ code if possible. I also need to be able to run the code on multiple processors effectively in a controlled manner.

我看了几个现成的口译员,但找不到我想要的东西。我考虑过JAVA,因为它非常快,但是我需要加载JAVA虚拟机,这意味着在C和虚拟机之间传递对象......接口是这里的瓶颈。我真的需要创建一个运行C ++代码的本机C ++对象。我还需要能够以受控方式有效地在多个处理器上运行代码。

I'm not looking for the whole explanation on how to pull this off, as I can do my own research. I've been stalled for a couple days here now, however, and I really need a place to start looking.

我不是在寻找关于如何解决这个问题的全部解释,因为我可以做自己的研究。我现在已经在这里待了几天,但是,我真的需要一个地方开始寻找。

As a last resort, I will create my own scripting language to fulfill the need, but that seems a waste with all the great interpreters out there. I've also considered taking an existing open source complier and slicing it up for the functionality I need... just not saving the compiled results to disk... I don't know. I would prefer to use a mainline language if possible... but that's not required.

作为最后的手段,我将创建自己的脚本语言以满足需求,但这似乎是所有伟大的口译员的浪费。我还考虑过使用现有的开源编译器并将其切换为我需要的功能...只是不将编译结果保存到磁盘......我不知道。如果可能的话,我宁愿使用主线语言......但这不是必需的。

Any help would be appreciated. I know this is not your run of the mill idea I have here, but someone has to have done it before.

任何帮助,将不胜感激。我知道这不是你在这里的磨坊想法,但有人必须先做过。

Thanks!

P.S. One thought that just occurred to me while writing this was this: what about using a true C compiler to create object code, save it to disk as a dll library, then reload and run it inside "my" code? Can you do that with MS Visual Studio? I need to look at the licensing of the compiler... how to reload the library dynamically while the main application continues to run... hmmmmm I could then just group the "functions" created by the user into library groups. Ok that's enough of this particular brain dump...

附:在我写这篇文章时我想到的一个想法是:使用真正的C编译器创建目标代码,将其作为dll库保存到磁盘,然后在“我的”代码中重新加载并运行它?你能用MS Visual Studio做到吗?我需要查看编译器的许可...如何在主应用程序继续运行时动态重新加载库...嗯,我可以将用户创建的“函数”分组到库组中。好吧,这个特定的大脑转储就够了......

2 个解决方案

#1


A possible solution could be use gcc (MingW since you are on windows) and build a DLL out of your user defined code. The DLL should export just one function. You can use the win32 API to handle the DLL (LoadLibrary/GetProcAddress etc.) At the end of this job you have a C style function pointer. The problem now are arguments. If your computation has just one parameter you can fo a cast to double (*funct)(double), but if you have many parameters you need to match them.

一个可能的解决方案可能是使用gcc(MingW,因为你在Windows上)并使用用户定义的代码构建DLL。 DLL应该只导出一个函数。您可以使用win32 API来处理DLL(LoadLibrary / GetProcAddress等)。在此作业结束时,您有一个C样式函数指针。现在的问题是争论。如果您的计算只有一个参数,您可以将强制转换为double(* funct)(double),但如果您有许多参数,则需要匹配它们。

#2


I think I've found a way to do this using standard C.

我想我已经找到了一种方法来使用标准C.

1) Standard C needs to be used because when it is compiled into a dll, the resulting interface is cross compatible with multiple compilers. I plan to do my primary development with MS Visual Studio and compile objects in my application using gcc (windows version)

1)需要使用标准C,因为当它被编译成dll时,生成的接口与多个编译器交叉兼容。我计划用MS Visual Studio进行主要开发,并使用gcc(windows版本)在我的应用程序中编译对象

2) I will expose certain variables to the user (inputs and outputs) and standardize them across units. This allows multiple units to be developed with the same interface.

2)我将向用户公开某些变量(输入和输出)并跨单位标准化它们。这允许使用相同的接口开发多个单元。

3) The user will only create the inside of the function using standard C syntax and grammar. I will then wrap that function with text to fully define the function and it's environment (remember those variables I intend to expose?) I can also group multiple functions under a single executable unit (dll) using name parameters.

3)用户只能使用标准C语法和语法创建函数内部。然后我将用文本包装该函数以完全定义函数及其环境(还记得我打算公开的那些变量吗?)我还可以使用名称参数在单个可执行单元(dll)下组合多个函数。

4) When the user wishes to test their function, I dump the dll from memory, compile their code with my wrappers in gcc, and then reload the dll into memory and run it. I would let them define inputs and outputs for testing.

4)当用户希望测试它们的功能时,我从内存中转储dll,用gcc中的包装器编译它们的代码,然后将dll重新加载到内存中并运行它。我会让他们定义用于测试的输入和输出。

5) Once the test/create step was complete, I have a compiled library created which can be loaded at run time and handled via pointers. The inputs and outputs would be standardized, so I would always know what my I/O was.

5)一旦测试/创建步骤完成,我就会创建一个编译库,可以在运行时加载并通过指针处理。输入和输出将是标准化的,所以我总是知道我的I / O是什么。

6) The only problem with standardized I/O is that some of the inputs and outputs are likely to not be used. I need to see if I can put default values in or something.

6)标准化I / O的唯一问题是可能不使用某些输入和输出。我需要看看我是否可以输入默认值。

So, to sum up:

所以,总结一下:

Think of an app with a text box and a few buttons. You are told that your inputs are named A, B, and C and that your outputs are X, Y, and Z of specified types. You then write a function using standard C code, and with functions from the specified libraries (I'm thinking math etc.)

想想带有文本框和几个按钮的应用程序。您被告知您的输入名为A,B和C,并且您的输出是指定类型的X,Y和Z.然后使用标准C代码和指定库中的函数编写函数(我在想数学等)

So now your done... you see a few boxes below to define your input. You fill them in and hit the TEST button. This would wrap your code in a function context, dump the existing dll from memory (if it exists) and compile your code along with any other functions in the same group (another parameter you could define, basically just a name to the user.) It then runs the function using a functional pointer, using the inputs defined in the UI. The outputs are sent to the user so they can determine if their function works. If there are any compilation errors, that would also be outputted to the user.

所以现在你完成了......你会看到下面的几个框来定义你的输入。你填写它们并点击TEST按钮。这会将您的代码包装在函数上下文中,从内存中转储现有的dll(如果存在)并将代码与同一组中的任何其他函数一起编译(您可以定义的另一个参数,基本上只是用户的名称。)然后,它使用功能指针运行该功能,使用UI中定义的输入。输出将发送给用户,以便他们确定其功能是否有效。如果有任何编译错误,那么也会输出给用户。

Now it's time to run for real. Of course I kept track of what functions are where, so I dynamically open the dll, and load all the functions into memory with functional pointers. I start shoving data into one side and the functions give me the answers I need. There would be some overhead to track I/O and to make sure the functions are called in the right order, but the execution would be at compiled machine code speeds... which is my primary requirement.

现在是时候竞争真实了。当然我跟踪了哪些函数在哪里,所以我动态打开dll,并用函数指针将所有函数加载到内存中。我开始把数据推到一边,功能给了我需要的答案。跟踪I / O并确保以正确的顺序调用函数会有一些开销,但执行将是编译的机器代码速度......这是我的主要要求。

Now... I have explained what I think will work in two different ways. Can you think of anything that would keep this from working, or perhaps any advice/gotchas/lessons learned that would help me out? Anything from the type of interface to tips on dynamically loading dll's in this manner to using the gcc compiler this way... etc would be most helpful.

现在......我已经用两种不同的方式解释了我的想法。你能想到任何可以阻止它工作的东西,或者任何可以帮助我的建议/陷阱/经验教训吗?从接口类型到以这种方式动态加载dll的提示,以这种方式使用gcc编译器......等等都是最有帮助的。

Thanks!

#1


A possible solution could be use gcc (MingW since you are on windows) and build a DLL out of your user defined code. The DLL should export just one function. You can use the win32 API to handle the DLL (LoadLibrary/GetProcAddress etc.) At the end of this job you have a C style function pointer. The problem now are arguments. If your computation has just one parameter you can fo a cast to double (*funct)(double), but if you have many parameters you need to match them.

一个可能的解决方案可能是使用gcc(MingW,因为你在Windows上)并使用用户定义的代码构建DLL。 DLL应该只导出一个函数。您可以使用win32 API来处理DLL(LoadLibrary / GetProcAddress等)。在此作业结束时,您有一个C样式函数指针。现在的问题是争论。如果您的计算只有一个参数,您可以将强制转换为double(* funct)(double),但如果您有许多参数,则需要匹配它们。

#2


I think I've found a way to do this using standard C.

我想我已经找到了一种方法来使用标准C.

1) Standard C needs to be used because when it is compiled into a dll, the resulting interface is cross compatible with multiple compilers. I plan to do my primary development with MS Visual Studio and compile objects in my application using gcc (windows version)

1)需要使用标准C,因为当它被编译成dll时,生成的接口与多个编译器交叉兼容。我计划用MS Visual Studio进行主要开发,并使用gcc(windows版本)在我的应用程序中编译对象

2) I will expose certain variables to the user (inputs and outputs) and standardize them across units. This allows multiple units to be developed with the same interface.

2)我将向用户公开某些变量(输入和输出)并跨单位标准化它们。这允许使用相同的接口开发多个单元。

3) The user will only create the inside of the function using standard C syntax and grammar. I will then wrap that function with text to fully define the function and it's environment (remember those variables I intend to expose?) I can also group multiple functions under a single executable unit (dll) using name parameters.

3)用户只能使用标准C语法和语法创建函数内部。然后我将用文本包装该函数以完全定义函数及其环境(还记得我打算公开的那些变量吗?)我还可以使用名称参数在单个可执行单元(dll)下组合多个函数。

4) When the user wishes to test their function, I dump the dll from memory, compile their code with my wrappers in gcc, and then reload the dll into memory and run it. I would let them define inputs and outputs for testing.

4)当用户希望测试它们的功能时,我从内存中转储dll,用gcc中的包装器编译它们的代码,然后将dll重新加载到内存中并运行它。我会让他们定义用于测试的输入和输出。

5) Once the test/create step was complete, I have a compiled library created which can be loaded at run time and handled via pointers. The inputs and outputs would be standardized, so I would always know what my I/O was.

5)一旦测试/创建步骤完成,我就会创建一个编译库,可以在运行时加载并通过指针处理。输入和输出将是标准化的,所以我总是知道我的I / O是什么。

6) The only problem with standardized I/O is that some of the inputs and outputs are likely to not be used. I need to see if I can put default values in or something.

6)标准化I / O的唯一问题是可能不使用某些输入和输出。我需要看看我是否可以输入默认值。

So, to sum up:

所以,总结一下:

Think of an app with a text box and a few buttons. You are told that your inputs are named A, B, and C and that your outputs are X, Y, and Z of specified types. You then write a function using standard C code, and with functions from the specified libraries (I'm thinking math etc.)

想想带有文本框和几个按钮的应用程序。您被告知您的输入名为A,B和C,并且您的输出是指定类型的X,Y和Z.然后使用标准C代码和指定库中的函数编写函数(我在想数学等)

So now your done... you see a few boxes below to define your input. You fill them in and hit the TEST button. This would wrap your code in a function context, dump the existing dll from memory (if it exists) and compile your code along with any other functions in the same group (another parameter you could define, basically just a name to the user.) It then runs the function using a functional pointer, using the inputs defined in the UI. The outputs are sent to the user so they can determine if their function works. If there are any compilation errors, that would also be outputted to the user.

所以现在你完成了......你会看到下面的几个框来定义你的输入。你填写它们并点击TEST按钮。这会将您的代码包装在函数上下文中,从内存中转储现有的dll(如果存在)并将代码与同一组中的任何其他函数一起编译(您可以定义的另一个参数,基本上只是用户的名称。)然后,它使用功能指针运行该功能,使用UI中定义的输入。输出将发送给用户,以便他们确定其功能是否有效。如果有任何编译错误,那么也会输出给用户。

Now it's time to run for real. Of course I kept track of what functions are where, so I dynamically open the dll, and load all the functions into memory with functional pointers. I start shoving data into one side and the functions give me the answers I need. There would be some overhead to track I/O and to make sure the functions are called in the right order, but the execution would be at compiled machine code speeds... which is my primary requirement.

现在是时候竞争真实了。当然我跟踪了哪些函数在哪里,所以我动态打开dll,并用函数指针将所有函数加载到内存中。我开始把数据推到一边,功能给了我需要的答案。跟踪I / O并确保以正确的顺序调用函数会有一些开销,但执行将是编译的机器代码速度......这是我的主要要求。

Now... I have explained what I think will work in two different ways. Can you think of anything that would keep this from working, or perhaps any advice/gotchas/lessons learned that would help me out? Anything from the type of interface to tips on dynamically loading dll's in this manner to using the gcc compiler this way... etc would be most helpful.

现在......我已经用两种不同的方式解释了我的想法。你能想到任何可以阻止它工作的东西,或者任何可以帮助我的建议/陷阱/经验教训吗?从接口类型到以这种方式动态加载dll的提示,以这种方式使用gcc编译器......等等都是最有帮助的。

Thanks!