Difference between revisions of "LuaBindingGuide"

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