views:

365

answers:

9

Dear all:

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++...

A: 

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

Ben Collins
Again, not looking for embeeding. Using V8 or Guile forces me to write ad-hoc wrappers for C++. I want the scripting language to be able to generate the .h and such.
Diego Sevilla
My fault for not reading your question carefully. I don't know of any language tools out there that would readily do what you want.
Ben Collins
A: 

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.

T.J. Crowder
Oh, no, not embeeding, but that the scripting language be able to generate stand-alone .so modules (and the corresponding .h files to be used from C++)
Diego Sevilla
@Diego: Well, I expect you could wrap up some JavaScript code *and* the V8 interpreter into an `.so` :-) but I doubt that's what you mean. So, something that compiles JavaScript to machine code (rather than allowing JavaScript to talk seamlessly to C++) and does away with the garbage collector (probably by using reference counting instead) and other aspects of the interpreter. It's a tall order. V8 does compile JavaScript directly to machine code, but on-the-fly and in a dynamic way (because JavaScript is a dynamic language). Never heard of one for C++. [OT: There is one for Java (Rhino).]
T.J. Crowder
+2  A: 

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.

Dragontamer5788
My experience with Boost:Python was unhappy. The code also appeared to be rotting on the vine. SWIG was a much better experience.
Craig W. Wright
+8  A: 

The question usually asked in this context is: how do I expose my C++ classes so they can be instantiated from script? And the answer is often something like http://www.swig.org/

You're asking the opposite question and it sounds like you're complicating matters a bit. A scripting engine that produced .h files and .so files wouldn't really be a scripting engine - it would be a compiler! In which case you could use C++.

Scripting engines don't work like that. You pass them a script and some callbacks that provide a set of functions that can be called from the script, and the engine interprets the script.

Daniel Earwicker
Daniel, yes, scripting engines may do dynamic execution, but they may not. Maybe what I'm looking for, as I stated, is a scripting language instead of a scripting engine. Along the lines of GNOME's Vala, more an aid for writing fast code that it is converted to C++ (C in the case of Vala), or like ghc, that actually generates C code taking into account garbage collection, etc. It would be kind of a DSL for C++ that also has a run-time set of libraries that can be used. Maybe the google go language is the answer (curiously not mentioned by anyone)...
Diego Sevilla
Maybe because Go, like Lua and other languages, interfaces with C but not directly with C++... source : http://golang.org/doc/go_faq.html#Do_Go_programs_link_with_Cpp_programs
Klaim
Thanks I didn't know about Swig at all...
Bart J
+1  A: 

Good question, I have often thought about this myself, but alas there is no easy solution to this kind of thing. If you are on Windows (I guess not), then you could achieve something like this by creating COM components in C++ and VB (considering that as a scripting language). The talking happens through COM interfaces, which is a nice way to interop between disparate languages. Same holds for .NET based languages which can interop between themselves.

I too am eager to know if something like this exists for C++, preferably open source.

tathagata
"which is a nice way to interop ..." : I have to strongly disagree. COM (especially when used to interface VB and C++) is particularly difficult to use...
Alexandre C.
Okay, yes, COM interop has several quirks :), when used between C++ and VB, and maybe more so when between .NET and COM; you have thoroughly understand and memorized a lot of it, not something particularly well designed. I myself am not a fan of COM, and can hardly recommend it.
tathagata
+4  A: 

Try lua: http://www.lua.org/

For using C++ classes in lua you can use:

To generate binding use tolua++: http://www.codenix.com/~tolua/

It takes a cleaned up header as input and outputs a c file that does the hard work. Easy, nice and a pleasure to work with.

For using Lua objects in C++ I'd take the approach of writing a generic Proxy object with methods like (field, setField, callMethod, methods, fields).

If you want a dll you could have the .lua as a resource (in Windows, I don't know what could be a suitable equivalent for Linux) and on your DllMain initialize your proxy object with the lua code.

The c++ code can then use the proxy object to call the lua code, with maybe a few introspection methods in the proxy to make this task easier.

You could just reuse the proxy object for every lua library you want to write, just changing the lua code provided to it.

Vitor Py
A: 

You can do this with Lua, but if you have a lot of classes you'll want a tool like SWIG or toLua++ to generate some of the glue code for you.

None of these tools will handle the unusual part of your problem, which is to have a .h file behind which is hidden a scripting language, and to have your C++ code call scripts without knowing that that are scripts. To accomplish this, you will have to do the following:

  • Write the glue code yourself. (For Lua, this is relatively easy, until you get into classes, whereupon it's not so easy, which is why tools like SWIG and toLua++ exist.)

  • Hide behind the interface some kind of global state of the scripting interpreter.

  • Supposing you have multiple .h files that each are implemented using scripts, you have to decide which ones share state in the scripting language and which ones use separate scripting states. (What you basically have is a VM for the scripting language, and the extremes are (a) all .h files use the same VM in common and (b) each .h file has its own separate, isolated VM. Other choices are more complicated.)

If you decide to do this yourself, writing the glue code to turn Lua tables into C++ classes (so that Lua code looks like C++ to the rest of the program) is fairly straightforward. Going in the other direction, where you wrap your C++ in Lua (so that C++ objects look to the scripts like Lua values) is a big pain in the ass.

No matter what you do, you have some work ahead of you.

Norman Ramsey
+2  A: 

The following ones are more C++ integration oriented than language bindings :

  • ChaiScript - trying at the moment in a little project, interesting, this one is MADE with C++ in mind and works by just including a header! Not sure if it's good for a big project yet but will see, try it to have some taste!
  • Falcon - trying on a big project, excellent; it's not a "one include embed" as ChaiScript but it's because it's really flexible, and totally thought to be used in C++ (only C++ code in libs) - I've decided to stick with it for my biggest project that require a lot of scripting flexibility (comparable to ruby/python )
  • AngelScript - didn't try yet
  • GameMonkey - didn't try yet
  • Io - didn't try yet

For you, if you really want to write your scripting module in C++ and easily expose it to the scripting language, I would recommand going with Falcon. It's totally MADE in C++, all the modules/libraries are written that way.

Klaim
Thanks, Klaim. This is the kind of answer I was looking for. I'm going to try your recommendations and let's see.
Diego Sevilla
No problem, I've done a lot of searching (with help on forums) to get this list of interesting scripting languages.
Klaim
A: 

Hi, I'm the author of LikeMagic, a C++ binding library for the Io language. (I am not the author of Io.)

http://github.com/dennisferron/LikeMagic

One of my explicit goals with LikeMagic is complete and total C++ interoperability, in both directions. LikeMagic will marshal native Io types as C++ types (including converting between STL containers and Io's native List type) and it will represent C++ classes, methods, fields, and arrays within Io. You can even pass a block of Io code out of the Io environment and use it in C++ as a functor!!

Wrapping C++ types up for consumption in Io script is simple, quick and easy. Accessing script objects from C++ does require an "eval" function like you described, but the template based type conversion and marshaling makes it easy to access the result of executing a script string. And there is the aforementioned ability to turn Io block() objects into C++ functors.

Right now the project is still in the early stages, although it is fully operational. I still need to do things like document its build steps and dependencies, and it can only be built with gcc 4.4.1+ (not Microsoft Visual C++) because it uses C++0x features not yet supported in MSVC. However, it does fully support Linux and Windows, and a Mac port is planned.

Now the bad news: Making the scripts produce .h files and .so or .dll files callable from C++ would not only require a compiler (of a sort) but it would also have to be a JIT compiler. That's because (in many scripting languages, but most especially in Io) an object's methods and fields are not known until runtime - and in Io, methods can even be added and removed from live objects! At first I was going to say that the very fact that you're asking for this makes me wonder if perhaps you don't really understand what a dynamic language is. But I do believe in a way of design in which you first try to imagine the ideal or easiest possible way of doing something, and then work backwards from there to what is actually possible. And so I'll admit from an ease-of-use standpoint, what you describe sounds easier to use.

But while it's ideal, and just barely possible (using a script language with JIT compilation), it isn't very practical, so I'm still unsure if what you're asking for is what you really want. If the .h and .so/.dll files are JITted from the script, and the script changes, you'd need to recompile your C++ program to take advantage of the change! Doesn't that violate the main benefit of using script in the first place?

The only way it is practical would be if the interfaces defined the scripts do not change, and you just are making C++ wrappers for script functions. You'd end up having a lot of C++ functions like:

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

I will admit that's cleaner looking code from the point of view of the callers of the wrapper function. But if that's what you want, why not just use reflection in the scripting language and generate a .h file off of the method lists stored in the script objects? This kind of reflection can be easily done in Io. At some point I plan to integrate the OpenC++ source-to-source translator as a callable library from LikeMagic, which means you could even use a robust C++ code generator instead of writing out strings.

Dennis