• 9
• 10
• 9
• 10
• 10
• entries
108
319
• views
137856

# More Lua

375 views

Well, I decided to have a go at more scripting and I made huge progress. I have quite the nice framework for a scripting engine going using Lua. No screenshot for you guys today, but here is an example of what you can do with the wrapper so far:

#include #include "scriptengine.h"using namespace std;int main(){    ScriptEngine Lua;        // Run script.txt    Lua.RunFile("script.txt");        // Get a variable    int num;    if( !Lua.GetVariable("VariableName", num) ) // put it into num        cout << "Error loading the variable" << endl;        cout << "VariableName is " << num;        // Run a script function named SomeFunction    Lua.CallFunction("SomeFunction");    // Run a script function with 3 arguments    Lua.CallFunction("SomeArgumentFunction", "Arg1|Arg2|Arg3");    // Run a script function with an argument and return a value    int output;    Lua.CallFunctionReturn("Double", output, 5);        cout << "The Double of 5 is " << output;                return 0;}

I'm still working out some bugs on each function and need to do some brainstorming about getting CallFunction and CallFunctionReturn into the same function. I could even try and find out how the int foo(std::string arg, ... ) functions work. Now that would be pretty cool. I could have something like:
bool CallFunction(std::string functionName, std::string* output, std::string argument, ... );
... Now that would be fancy. If you didn't want a return type you could just pass in NULL.

I also got calling C++ functions from the script working as well, but it's a bit more complex and I'm still kind of brainstorming some different solutions to wrap it up. Yes, I know I should check out LuaBind or ToLua, but I'm having fun with this! I decided to go with Lua instead of Squirrel or GameMonkey or anything else as it has been proven to work in games and large applications. I'm not saying that nothing else has, I'm just saying that this is a good solution to pick. It also has a huge user community which means lots of documentation.

As for what's up next, I'd like to:
• Make the script C++ function calls easier to understand
• Improve error handling (everything just returns true or false if it works or not right now)
• Run script from an std::string
• Modify/change in-script variables from C++
• Modfiy/set C++ variables from the script
• Script array/table handling in C++
• Other in-script functions to make life easier
• Easy C++ object modification from Lua
• Check out lua-users some more
• Figure out cstdarg so that I can have variable argument lists for CallFunction()
• Combine CallFunction() and CallFunctionReturn() if possible
... Looks like I have quite a ways to go. If you guys have any thoughts on the design, please tell me!

### Random Interest

Monkey vs Tiger

My advice: Avoid variable argument lists like the plague. They are very bug-prone. And their bugs are generally really hard to spot. I work regularly on PalmOS, where all the time you're working with physical memory (i.e. No virtual address space for your process, mess up and write one byte in the wrong place, and you end up freezing the OS). At one point we had an snprintf bug that was almost impossible to catch, if it weren't for gcc's smart reporting (gcc has a flag to check that you've supplied the right parameters to variable argument functions that take a format-string).

EDIT: We don't use gcc for development, by the way. We use CodeWarrior - we only used gcc for testing.

So you'd recommend sticking with an argument list that is one string separated by a '|'?

Sorry for the late reply - wasn't in the mood for writing anything yesterday.

Anyway, regarding your argument list. What you want to do depends on what you expect you'll be doing. Unless all your argument lists are expected to be known at compile-time (i.e. can be hard-wired as a string literal), you shouldn't be doing it that way. It'd be awkward to do things like passing 2 integer arguments, one float and a string to a function - In that case, you'll need a temporary stringstream or equivalent.
Basically, I find the "|"-based solution kind of primitive, or too low level.

What I always like to do with my designs is do it top-down. How would I like to be passing arguments?
Here are some attempts/thoughts that you might find useful.

Attempt #1:
Scripting::ArgumentList args;
args[0] = "Hey";
args[1] = 5;
args[2] = 10;
args[3] = 45.5f;
Lua.CallFunction("DoThis", args);

Too long. Too tiresome.

Attempt #2:
Scripting::ArgumentList args;
args<< "Hey"<< 5<< 10<< 45.5f;
Lua.CallFunction("DoThis", args);

Still too long. But it can be shorter:

Attempt #3:
Lua.CallFunction("DoThis", Scripting::ArgumentList()<< "Hey"<< 5<< 10<< 45.5f);

Looks kind of weird at first, but it's much shorter. I use this style often with wxStrings (wxWidgets strings).

From an implementation point of view, all the previous attempts are fairly obvious, so I won't discuss it.

Regarding setting/getting variables from C++, you could overload the [] operator to do that for you, std::map style.

script["speed"] = 5;

That's it for now - if I have any smart revelations during the day, I'll come back and share it [smile]