I have come across the need to use a scripting engine for my C++ game, but after experimenting with many languages since the last few days, nothing has truly stood out as the obvious choice for a language and/or binding library.

I would like have the ability to

call methods of a specific Game instance from within the scripting language,

call arbitrary functions in the scripts from C++, and

test for function existence in the scripts using strings.

Lua looks nice, but I'm unsure of its ability to do 1 and 3. Python and Boost::Python are great, but the same applies. Regardless, here's an example of an ideal implementation.

Could you explain 3. a bit more? I am pretty sure Lua is able to do 1 but I am not sure I am understanding what the last one would do to venture a guess as to if Lua does it or can be altered to do it. (Might be as simple as looking through the global tables or an objects table to see if a method of the same name is defined already or not).
–
JamesMar 3 '12 at 0:13

Sure! The script may or may not contain, say a function called hero_dies(). I can just imagine the problems that would emerge from C++ attempting to call a nonexistent script function, so I would like to be able to test for existence before calling, otherwise fail silently. If the Lua binding by default ignores nonexistent calls, then I won't need to worry about (3).
–
VorticoMar 3 '12 at 0:20

Oh, I was thinking the other way around. Let me see if I can not figure out what happens (would assume the call just fails in a handle-able manner but seeing as I have never had that situation, I am not going to bet an answer on it :))
–
JamesMar 3 '12 at 0:26

(1) is the major issue though. I was able to call script functions from C++ and static C++ functions from scripts, but I couldn't figure out how to set a global "game" variable in the scripting environment which would correspond to the "Game *game" pointer defined in C++'s main(). The script writer would then have global access to this object, and manipulating the game properties through the scripting language would become extremely efficient.
–
VorticoMar 3 '12 at 0:28

Boost::Python can do 1 and 3. When you write C++ code you use boost to write python class description (basically you will make two classes, not two implementations, one for C++ one for python), so... python has class and you can use reflection to do 3.
–
Edin M.Mar 18 '12 at 12:17

2 Answers
2

I'm fairly sure Lua can do everything you need relatively simply. I use Lua and C++ in my game. I looked at various wrappers like LuaBind, or using a generator like Swig, but I decided I didn't want any of that stuff and I wrote my own wrapper which I ended up making open source in case other people found it useful.

local w = Widget.new()
w.foo = 10 -- Foo is stored on w, it's not accessible to other instances
-- You can also add values accessible to all Widgets
function Widget.metatable:newfunction()
print(self:GetWidth())
end
w:newfunction()

With all that, you can fairly easily call C++ function from Lua (and vice versa, but I didn't illustrate that here). Once you know how to interact with the Lua API, writing a function to 'safely' call (i.e. call a function only if it exists) a Lua function should be easy as well.

Edit:

If you want to check for the existence of a function before calling it, like I said, just check that the value is a function before calling it.

lua_getglobal(L, "myFunc"); // You can get your function from anywhere, this is just for example
if (lua_isfunction(L, -1)) // Check the top of the stack, make sure it's a function
{
lua_call(L, 0, 0);
}

1 and 2 are easy from what I recall (and I also agree that most wrapping libs out there are overly complicated and so usually roll my own). But what I am trying to find out is if there is a test for the existence of a function or method. Most of the calls to execute a lua function from C do not appear to return. Assuming that if the script compiled the syntax was atleast ok, that just leaves invalid arguments vs undefined call, but I have not been able to find a way to determine which is which yet :)
–
JamesMar 3 '12 at 1:04

Are you familiar with how to call Lua functions from the C API? If you know how to do that, just do a nil check before calling your function. It's super easy. I'll update my answer with an example momentarily
–
Alex AmesMar 3 '12 at 1:07

In the API summary: "Objects can be created in either Lua or C++, and passed back and forth." I'm sold. I will try this out tonight.
–
VorticoMar 3 '12 at 1:19

I'm somewhat familiar with the Lua API, but only two days worth. Do I use lua_isnil(L, 1)? Is index 1 always the name of the called function?
–
VorticoMar 3 '12 at 1:22

If you're not familiar with the Lua API (either the C API or the language itself) I suggest you read through Programming In Lua. You should be able to get through the whole tutorial in a weekend or so. There's also the Lua Reference Manual. To answer your question, Lua works with stack. 1 is the bottom of the stack. If you want to count from the top down, you can use negative numbers. For exmaple, -1 is the value at the top of the stack. It'll make more sense if you read the tutorial.
–
Alex AmesMar 3 '12 at 1:29

You can easily create different scripting contexts, and for some types of scripts, have functionality x, for others, y. For example if you want to have a game loop in a script, and AI specific functions in other, while hiding the other one's API.

You can call functions by their name, you can export global functions and class members easily.
You can define global properties as well.

So you could basically configure your script to know a Game object, which is your actual Game instance. Then call functions exported on it.

Its really straightforward, but if you want I can add little snippets of how it could be done. Though, we re talking about 1-line setups !

This also looks like a possibility. It seems like it's designed to "take over" more of the C++ work than what I had intended, but the C++ glue code looks simple enough to make the change worth it. In your experiences, how have you been able to debug your AngelScript code?
–
VorticoMar 4 '12 at 0:56

Well, when something goes wrong, it warns you through a message callback. Also, in debug mode it outputs a call stack to a file. Besides, from the nature of the scripting language, I believe it makes your life easy to make safe environments, where only a limited, granted to work functionality can be called.
–
GrimshawMar 4 '12 at 1:01