42

I'm getting a little rusty in scripting languages, provided they're popping like mushrooms lately :)

Today I thought that it would be nice to have a scripting language that talks seamlessly to C++, that is, could use C++ classes, and, the most important for me, could be compiled into C++ or some DLL/.SO (plus its .h) so that I could link it into my C++ program and make use of the classes the script defines or implements.

I know I could embed any popular scripting language such as lua, ruby, python... but the interface usually includes some kind of "eval" function that evaluates the provided scripting code. Depending on the tool used to couple C++ and the scripting language, the integration for callbacks of the script into C++ could be more or less easy to write, but I haven't seen any scripting language that actually allows me to write independent modules that are exposed as a .h and .so/dll to my program (maybe along the lines of a scripting language that generates C++ code).

Do you know any such tool/scripting language?

Thanks in advance.

PD. I've been thinking along the lines of Vala or Haskell's GHC. They generate C, but not C++...

4

10 回答 10

35

2020 年更新:今天我可能会使用 Lua + Sol2/3,除非我真的想避免将 Lua 作为一门语言。在这种情况下,Chaiscript 成为一个很好的候选者,尽管与 Lua+Sol2/3 相比,它在性能方面并不是最优的(尽管它经过多年的极大改进,因此在许多情况下仍然足够好)。猎鹰已经死了好几年了,安息吧。


以下是比语言绑定更面向 C++ 集成:

  • ChaiScript - 目前正在尝试一个小项目,有趣的是,这个项目是用 C++ 制作的,只需包含一个标题即可!不确定它是否适合大型项目,但会看到,尝试一下!
  • (不再维护) Falcon - 尝试一个大项目,非常好;它不是 ChaiScript 的“一个包含嵌入”,而是因为它非常灵活,并且完全被认为可以在 C++ 中使用(只有库中的 C++ 代码)——我决定在我最大的项目中坚持使用它,这需要很多脚本灵活性(与 ruby​​/python 相当)
  • AngelScript - 还没有尝试
  • GameMonkey - 还没试过
  • io - 还没试过

对您而言,如果您真的想用 C++ 编写脚本模块并轻松地将其暴露给脚本语言,我建议您使用 Falcon。它完全是用 C++ 制作的,所有的模块/库都是这样编写的。

于 2010-06-30T21:10:13.280 回答
21

试试 lua:http ://www.lua.org/

要在 lua 中使用 C++ 类,您可以使用:

要生成绑定使用 tolua++: http: //www.codenix.com/~tolua/

它需要一个清理过的标头作为输入,并输出完成艰苦工作的 ac 文件。轻松、愉快、愉快地合作。

为了在 C++ 中使用 Lua 对象,我会采用编写通用代理对象的方法,方法是(field、setField、callMethod、methods、fields)。

如果你想要一个 dll,你可以将 .lua 作为资源(在 Windows 中,我不知道什么是适合 Linux 的等价物)并在你的 DllMain 上用 lua 代码初始化你的代理对象。

然后 c++ 代码可以使用代理对象调用 lua 代码,可能在代理中使用一些自省方法来简化此任务。

您可以为要编写的每个 lua 库重用代理对象,只需更改提供给它的 lua 代码。

于 2010-06-30T15:21:38.827 回答
21

在这种情况下通常会问的问题是:如何公开我的 C++ 类,以便它们可以从脚本中实例化?答案通常类似于http://www.swig.org/

你问的是相反的问题,听起来你让事情变得复杂了一点。生成 .h 文件和 .so 文件的脚本引擎并不是真正的脚本引擎 - 它是编译器!在这种情况下,您可以使用 C++。

脚本引擎不是那样工作的。你向他们传递一个脚本和一些回调,这些回调提供了一组可以从脚本调用的函数,引擎会解释脚本。

于 2010-06-30T15:01:49.087 回答
12

This is slightly outside my area of expertise, but I'm willing to risk the downvotes. :-)

Boost::Python seems to be what you're looking for. It uses a bit of macro magic to do its stuff, but it does expose Python classes to C++ rather cleanly.

于 2010-06-30T14:59:00.113 回答
5

我是 LikeMagic 的作者,这是一个用于 Io 语言的 C++ 绑定库。(我不是 Io 的作者。)

http://github.com/dennisferron/LikeMagic

我对 LikeMagic 的明确目标之一是在两个方向上实现完整且完全的 C++ 互操作性。LikeMagic 会将原生 Io 类型编组为 C++ 类型(包括在 STL 容器和 Io 的原生 List 类型之间进行转换),它将表示 Io 中的 C++ 类、方法、字段和数组。您甚至可以将 Io 代码块从 Io 环境中传递出去,并在 C++ 中将其用作仿函数!

在 Io 脚本中包装 C++ 类型以供使用是简单、快速和容易的。从 C++ 访问脚本对象确实需要像您描述的那样的“eval”函数,但是基于模板的类型转换和封送处理使得访问执行脚本字符串的结果变得容易。还有前面提到的将 Io block() 对象转换为 C++ 函子的能力。

目前,该项目仍处于早期阶段,但已全面投入运营。我仍然需要做一些事情,比如记录它的构建步骤和依赖关系,它只能用 gcc 4.4.1+(不是 Microsoft Visual C++)构建,因为它使用了 MSVC 尚不支持的 C++0x 特性。但是,它确实完全支持 Linux 和 Windows,并计划推出 Mac 端口。

现在坏消息是:使脚本生成可从 C++ 调用的 .h 文件和 .so 或 .dll 文件不仅需要编译器(某种),而且还必须是JIT 编译器。这是因为(在许多脚本语言中,尤其是在 Io 中)对象的方法和字段直到运行时才知道 - 而在 Io 中,甚至可以从活动对象中添加和删除方法!起初我要说的是,你要求这个的事实让我想知道你是否真的不明白什么是动态语言. 但我确实相信一种设计方式,在这种设计方式中,您首先尝试想象做某事的理想或最简单的可能方式,然后从那里倒推到实际可行的方式。所以我承认,从易用性的角度来看,你所描述的听起来更容易使用。

但是,虽然它很理想,而且几乎不可能(使用带有 JIT 编译的脚本语言),但它不是很实用,所以我仍然不确定你所要求的是否是你真正想要的。如果 .h 和 .so/.dll 文件是从脚本中 JIT 生成的,并且脚本发生了更改,则您需要重新编译 C++ 程序以利用更改!这不是首先违反使用脚本的主要好处吗?

唯一可行的方法是,如果定义脚本的接口不改变,而您只是为脚本函数制作 C++ 包装器。你最终会拥有很多 C++ 函数,例如:

int get_foo() { return script.eval("get_foo()"); }
int get_bar() { return script.eval("get_bar()"); }

我承认从包装函数的调用者的角度来看,这是更简洁的代码。但是,如果这就是您想要的,为什么不直接在脚本语言中使用反射并从存储在脚本对象中的方法列表中生成一个 .h 文件呢?这种反射可以在 Io 中轻松完成。在某个时候,我计划将OpenC++ 源到源转换器集成为 LikeMagic 的可调用库,这意味着您甚至可以使用强大的 C++ 代码生成器而不是写出字符串。

于 2010-06-30T22:52:13.023 回答
2

你可以用 Lua 做到这一点,但如果你有很多类,你会需要一个像 SWIG 或 toLua++ 这样的工具来为你生成一些胶水代码。

这些工具都不会处理您的问题的不寻常部分,即有一个隐藏在脚本语言后面的 .h 文件,并让您的 C++ 代码调用脚本而不知道那是脚本。为此,您必须执行以下操作:

  • 自己编写胶水代码。(对于 Lua 来说,这相对容易,直到你进入课程,这并不容易,这就是存在 SWIG 和 toLua++ 等工具的原因。)

  • 隐藏在界面后面的脚本解释器的某种全局状态。

  • 假设您有多个 .h 文件,每个文件都使用脚本实现,您必须决定哪些共享脚本语言中的状态,哪些使用单独的脚本状态。(您基本上拥有的是用于脚本语言的 VM,极端情况是(a)所有 .h 文件都使用相同的 VM,(b)每个 .h 文件都有自己独立的、隔离的 VM。其他选择更多复杂。)

如果您决定自己这样做,编写胶水代码将 Lua 表转换为 C++ 类(这样 Lua 代码在程序的其余部分看起来就像 C++)相当简单。朝另一个方向发展,将 C++ 包装在 Lua 中(以便 C++ 对象看起来像 Lua 值一样的脚本)是一个很大的麻烦。

不管你做什么,你都有一些工作要做。

于 2010-06-30T20:34:49.310 回答
1

Google's V8 engine is written in C++, I expect you might be able to integrate it into a project. They talk about doing that in this article.

于 2010-06-30T14:57:40.063 回答
1

好问题,我自己也经常考虑这个问题,但是这种事情没有简单的解决方案。如果您在 Windows 上(我猜不是),那么您可以通过在 C++ 和 VB 中创建 COM 组件(将其视为脚本语言)来实现类似的效果。对话是通过 COM 接口进行的,这是一种在不同语言之间进行互操作的好方法。同样适用于可以在它们之间互操作的基于 .NET 的语言。

我也很想知道 C++ 是否存在类似的东西,最好是开源的。

于 2010-06-30T15:09:39.900 回答
0

You might check into embedding Guile (a scheme interpreter) or V8 (Google's javascript interpreter - used in Chrome - which is written in C++).

于 2010-06-30T14:57:19.033 回答
0

试试 Ring 编程语言 http://ring-lang.net

(1) 使用 C/C++ 语言的扩展 https://en.wikibooks.org/wiki/Ring/Lessons/Extension_using_the_C/C%2B%2B_languages

(2) 在 C/C++ 程序中嵌入环形解释器 https://en.wikibooks.org/wiki/Ring/Lessons/Embedding_Ring_Interpreter_in_C/C%2B%2B_Programs

(3) 用于包装 C/C++ 库的代码生成器 https://en.wikibooks.org/wiki/Ring/Lessons/Code_Generator_for_wrapping_C/C%2B%2B_Libraries

于 2016-03-22T07:25:44.267 回答