LuaBindingGuide
== luabindings for global functions == * lua can call special c functions that have a special prototype/parameter layout * to call arbitrary c functions from lua wrappers that match the prototype have to be created, we call those lua-bindings * global functions that can be called by lua all have this prototype : static int l_MyFunction (lua_State *L) { ... } * arguments from lua are passed on a stack and can be read using luaL_checkstring(L,1) ** index is one-based, eg starting from 1, 1st paramter is 1, 2nd is 2 etc, left to right. * the functions can return any number of values, including 0 or multiple * to add a return value to lua you push it onto the stack like this : lua_pushnumber(L,1); * the c functions c-return value is the number of lua-return-values pushed
== luabindings for c++ classes == * you can also create lua-bindings for entire c++ classes * if you want to create a lua-binding for the class cMyClass, * this class has to inherit from cSmartPointable * then you create a wrapper-class cMyClass_L that inherits cLuaBind<cMyClass> (you need luabind.h) * those wrapper classes are usually in extra files named _L.cpp * wrapped methods look like this : static int MyMethod (lua_State *L) { ... } * parameter access is similar to global functions, except that parameter indices start at 2, as 1 is for the implicit self * you cannot use this as the wrapper-methods have to be static, but you can get the implicit self by checkudata_alive(L) * checkudata_alive(L) = checkudata_alive(L,1) (you can also retrieve parameters that are objects with that) * all class-bindins have to have a unique typename : virtual const char* GetLuaTypeName () { return "sfz.objcontroller"; } * create new instances like this : return CreateUData(L,new cMyClass()); (pushes a lua-udata and returns 1) * method wrappers must be registered in the overridden RegisterMethods() method, usually via macro REGISTER_METHOD, see examples * you can also register member variables in some cases if you don't like manually implementing getter/setter, see gfx3D_L.cpp * the wrapper class has to be registered at startup : call from lua-plugin : static void LuaRegister (lua_State *L); ** where LuaRegister is a method that calls cLuaBind<cMyClass>::GetSingletonPtr(new cMyClass_L())->LuaRegister(L);
== tips and tricks == * for variable argument count, you can use lua_gettop(L) = c (-1 for methods due to implicit self) * for default argument value you can use this : int a = (lua_gettop(L) >= 2 && !lua_isnil(L,2)) ? luaL_checkint(L,2) : 0; * luaL_checkstring(L,2) returns const char* and is not valid for long, so you best assign it to an std::string * see l_GetAllKeyNames() in lugre_scripting.general.cpp for an example of how to return an array/table * you can call lua from c, but avoid that if possible (the application should be lua driven), search for examples similar to this : ** cScripting::GetSingletonPtr()->LuaCall("NotifyMainWindowResized","ii",w,h); ** it uses a variable argument-count syntax with format string remotely similar to printf ** it does support multiple returns by passing pointers and return format e ** e.g. LuaCall("MyLuaFun","i>ff",3,&fA,&fB) takes one integer and "returns" two doubles ** warning, there is no typechecking on the params, erros will lead to undefined behaviour : ** input/parameter values : i:int,f:double,s:char* ** output/return values : i:int*,f:double*,s:std::string* ** it only supports primitive parameter and return types, not tables/arrays ** you better avoid calling lua from c ** if you absolutely have to have to, please at least try to avoid using those ugly returnvalues * lua uses floats internally for all numbers ** there have been problems on some computers with 32 bit integer precision with compiler optimisation turned on in vs ** so if you need 32 bits you might want to use the pointertype lua_pushlightuserdata(...)