Difference between revisions of "LuaBindingGuide"
From SfzWiki
Ghoulsblade (Talk | contribs) |
Ghoulsblade (Talk | contribs) |
||
Line 1: | Line 1: | ||
+ | == 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(...) | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + |
Revision as of 12:52, 9 August 2007
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(...)