Where can I find tutorials/examples/etc. on how to integrate C++ and Lua?

Started by
5 comments, last by Serapth 11 years ago

EDIT: If anyone knows of any good alternatives to Lua as far as ease of implementation goes, I'd be very appreciative.

I wasn't going to do this, but after a whole day on Google I think with good conscious I can ask another question on here.

So I've heard a lot about Lua, I've read about it, I have a generally good idea how to write Lua script, I attempted to use it in one of the game engines I was working with, I believe and have faith in it... but I'm a little confused how to add it to my own game. Primarily because there are no decent examples or tutorials (online at least).

I should be a little bit more specific: I have the Lua libraries installed and linked to my project, I have "lua.hpp" included, I even have a little class for managing a lua state started. But it was at that point I realized I had no idea what I was doing. Like when I was learning SDL/Allegro/etc. I had similar feelings, but then because there's a wealth of information on the subject of how to manage a gameloop, drawing and flipping a buffer, how to manage different objects in a game environment... there's a lot of examples of best practices or at least tutorials on how to get your foot out the door.

But, while I've used game editors that use a scripting system (like RPGMaker uses Ruby, THAT WAS FUN LET ME TELL YOU, or Unity has Javascript/C#/Boo) I guess I don't really understand the concept behind integrating a scripting system into your game engine. Like I understand the concept of scripting, I have a lot of good ideas of how to use it... from the C++ side don't really know what to do.

TL;DR If you know any tutorials or sites where I can read through some examples, even if its some open source thing, to learn best practices or even just develop my own design theories around Lua, I would greatly appreciate it.

Please don't crucify me, I know this is a common topic but my journey through google was very... recursive, I think would be the best way to put it.

Also this:

lcj7ko.jpg

AniMerrill, a.k.a. Ethan Merrill

Advertisement
Lua is both very simple and very complex at the same time. Because it's so simple and flexible, and is designed to be embedded into apps as an "extension language", it is able to be used in many different ways. This means that the way that Lua is used by different applications can be quite different.
The best way to integrate it into your project then depends on how you want to use it.

First up, bookmark the manual, online tutorial book and wiki wink.png
http://www.lua.org/manual/
http://www.lua.org/pil/
http://lua-users.org/wiki/

The way that you connect your C++ code to your Lua code is usually called the binding system. There's many ways to do this, from writing the bindings yourself manually, or using a helper library that was designed for just this purpose. There's a wiki page that lists a bunch of these here: http://lua-users.org/wiki/BindingCodeToLua

Most people prefer a binding system, but some people do prefer to do it all manually. For example, the bitsquid engine authors argue that when you write the bindings manually, you end up creating a Lua API that is much more in the style of Lua, rather that one that is in the style of C++, and you are aware of any strange C++/Lua conversions that must take place.
If you don't want to do the bindings manually, then look through the binding systems in that link and pick one that meets your needs.


To manually bind a C function to Lua, you have to write a wrapper function that returns an int and takes a single argument of lua_State*. Inside that wrapper function, you can then pop your C function's arguments from the Lua strack, call your C function, then push it's return value to the lua stack (and then return the number of items you pushed).
Once you're written this function, you can give it to lua by use of the lua_pushcfunction method.

For example (using some copy&pasted helper functions from my own binding code), if in Lua I want to be able to write engine.DoStuff(1,2,3), I can use this code:
int Lua_DoStuff(lua_State* L)
{
	int numArgs = lua_gettop(L); // how many arguments the Lua caller put on the stack for us
	if( numArgs != 3 ) // If the lua user calls your API incorrectly, you can generate lua errors
		luaL_error(L, "Expected 3 args, received %d", numArgs );
	int a, b, c = ...//todo - pop arguments from stack
	float result = Actual_DoStuff( a, b, c );
	//todo push result to stack
	return /*num results pushed*/;
}
...
    Register(myLua, "engine", "DoStuff", &Lua_DoStuff );//register my C function with Lua, under the name "engine.DoStuff"
void PushNewGlobalTable(lua_State *L, const char* name, int nameLen)
{
	lua_pushlstring(L, name, nameLen);
	lua_pushvalue(L, -1);
	lua_rawget(L, LUA_GLOBALSINDEX);  /* get name */
	if (!lua_isnil(L, -1))  // name already in use?
	{
		lua_remove(L, -2); //remove name
		return;  // leave previous value on top
	}
	lua_pop(L, 1); // pop the nil
	lua_newtable(L);//todo - size hint?
	lua_pushvalue(L, -2);//push name
	lua_pushvalue(L, -2);//push table
	lua_rawset(L, LUA_GLOBALSINDEX);  // globals.name = table
	lua_remove(L, -2); //remove name
}

void Register(lua_State* L, const char* table, const char* method, int (*luaCall)(lua_State*))
{
	PushNewGlobalTable(L, table, strlen(table));
	lua_pushstring(L, method);
	lua_pushcfunction(L, luaCall);
	lua_rawset(L, -3);//table[method] = luaCall
	lua_pop(L, 2); // pop the tables
}
To manually call a Lua function from C, you push it to the stack, then push your args, then use pcall to execute it, then pop it's return value.
e.g. if you want to call the global Lua function "example()" from C, you could use
if( PushGlobalFunction(L, "example") ) // push function to stack
{
	int  numReturnValuesExpected = 0;
	int numArgumentsPushed = 0;
	//todo - push any arguments here
	int returnCode = lua_pcall(L, numArgumentsPushed, numReturnValuesExpected, 0);
	//pcall pops the arguments and the function from the stack, and replaces them with the return value
	if( returnCode )//pcall failed!
	{
		const char* errorText = lua_tostring(L, -1);//todo - print error
		lua_pop(L, 1);//pop error
	}
	else if( numReturnValuesExpected )
	{
		//todo - fetch/pop return value(s) here
	}
}
bool PushGlobalFunction(lua_State* L, const char* name)
{
	lua_pushstring(L, name);//push name
	lua_rawget(L, LUA_GLOBALSINDEX);//pops name, replaces it with _G[name]
	if(!lua_isfunction(L, -1))
	{
		lua_pop(L, 1); // not a function, pop it from stack and return error
		return false;
	}
	//our function is now on the top of the stack
	return true;
}

First up, bookmark the manual, online tutorial book and wiki

Thank you for your response, and last night while the forums were down I was reading through most of the manual- or at least the part regarding C implementation. I also found this tutorial once I realized that binding Lua to C/C++ was referred to as the "C API". The problem with just reading the manual and the book they have it it doesn't show you how to actually implement it even in a really simple example, its basically just showing you that you can use it. Yes that's a feature. You can do this.

After finding that tutorial, I guess I'll ask this question: are there any open source engines or simple open source games that demonstrate how they implemented Lua? Because the main thing I'm concerned about is losing the OOP integrity of what I have so far, trying to make it compatible with Lua and maybe some more concrete examples than a DoStuff() function..

AniMerrill, a.k.a. Ethan Merrill

Binding between C/C++ and Lua is relatively easy, but you do have to understand the stack structure and how userdata is represented. More importantly, though, is it is tedious. It's a bunch of boilerplate that you have to write for every single interface point. I don't know about you, but I've always hated writing boilerplate. It gets in the way of the good stuff.

This is why tools such as Luabind or tolua++ were born. To help eliminate some of the boilerplate-writing. You still do have to do a little bit (cleaning/modifying your headers, in the case of tolua, or coding the defs for Luabind) but tools like these greatly reduce the amount of it that you have to do. If your interface between C++ and Lua is extensive, using one of these can be of great benefit.

Just to follow up, LuaBind an tolua++ are REALLY easy and simple to bind C++ classes to lua.

Here is a tutorial of how to bind classes with LuaBind: http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/

You might have some problems in windows if you're new to programming thought.

I didn't find any compiled luabind for windows, but even so, its fairly easy to compile it from source code and the luabind manual has every instructions you might need to help you with that.

Just to follow up, LuaBind an tolua++ are REALLY easy and simple to bind C++ classes to lua.

Here is a tutorial of how to bind classes with LuaBind: http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/

You might have some problems in windows if you're new to programming thought.

I didn't find any compiled luabind for windows, but even so, its fairly easy to compile it from source code and the luabind manual has every instructions you might need to help you with that.

I guess I'll probably look into a binder. Was really hoping to get off scott free without needing another external library, I already have Allegro, but I suppose being able to use Lua is worth it. I'll need one that doesn't use Boost or another outside library though inside of it >__>

Guess it's back to Google now.

EDIT: Actually, now that I've been waffling around Lua for over 24 hours just to find a place to learn it (not learn it mind you, just trying to start) I've got to ask: with alternatives to Lua like Falcon and AngelScript, are there any alternatives to Lua someone might recommend? Even if Lua is industry standard, I'd be willing to admit I may need something with a lower entry cost of knowledge or implementation for my tiny, two man project.

35843775.jpg

AniMerrill, a.k.a. Ethan Merrill

Read the Moai source code too, it's on github. Its a C++ engine that "exposes itself" to Lua... it's some exceptionally clean C++ code, a very good read.

This topic is closed to new replies.

Advertisement