Advertisement
Dekowta

LuaBind

Jul 29th, 2012
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.63 KB | None | 0 0
  1. #include <lua.hpp>
  2. #include "cLua.h"
  3. #pragma once
  4.  
  5. ////////////////////////////////////////////////////////////////////////////////////////////////////
  6. //
  7. // This is a class bind that will be needed for any class that wants to be registered with Lua
  8. // I have taken this from http://cfc.kizzx2.com/index.php/binding-c-classes-to-lua-a-step-by-step-example-for-beginners/
  9. // which does a great job at explaining class binding (much better than I can) and
  10. // this site also uses the same method http://loadcode.blogspot.co.uk/2007/02/wrapping-c-classes-in-lua.html
  11. // both are great places to start to understand how it all works
  12. //
  13. //
  14. ////////////////////////////////////////////////////////////////////////////////////////////////////
  15.  
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // <summary>    is cLua. </summary>
  18. //
  19. // <remarks>    Chris, 29/07/2012. </remarks>
  20. //
  21. // <param name="LS">    [in,out] Lua State. </param>
  22. // <param name="index"> Zero-based index of the. </param>
  23. //
  24. // <returns>    null if it fails, else. </returns>
  25. //
  26. // <comment>    This function is used to obtain a cLua from the heap
  27. //              I am not 100% sure why it has to be a double pointer but I think its
  28. //              explained on the two links at the top
  29. //              the metatable "luaL_cLua" is used to check if it is the correct type or user data
  30. //              since we only want a single pointer we deref and return the pointer
  31. // </comment>
  32. ////////////////////////////////////////////////////////////////////////////////////////////////////
  33.  
  34. inline cLua* lua_iscLua(lua_State* LS, int index)
  35. {
  36.     return *(cLua**)luaL_checkudata(LS, index, "luaL_cLua");
  37. }
  38.  
  39. ////////////////////////////////////////////////////////////////////////////////////////////////////
  40. // <summary>    Lua pushc lua. </summary>
  41. //
  42. // <remarks>    Chris, 29/07/2012. </remarks>
  43. //
  44. // <param name="LS"> [in,out] Lua State. </param>
  45. // <param name="object">    [in,out] If non-null, a cLua object. </param>
  46. //
  47. // <returns>    null if it fails, else. </returns>
  48. //
  49. // <comment>    This uses the same method for creating a new object but instead of
  50. //              creating it as new a pointer to a similar object is set
  51. //              this will then push a new lua object but it will still be
  52. //              the same as class passed to this function
  53. // </comment>
  54. ////////////////////////////////////////////////////////////////////////////////////////////////////
  55.  
  56. inline cLua* lua_pushcLua(lua_State* LS, cLua* object)
  57. {
  58.     //create a new userdata
  59.     cLua** uData = (cLua**)lua_newuserdata(LS, sizeof(cLua*));
  60.     *uData = object; //set that user data to be equal to the passed in object
  61.     luaL_getmetatable(LS, "luaL_cLua"); //get and set the metatable for the new object in lua
  62.     lua_setmetatable(LS, -2);
  63.     return *uData; //return the new userdata if it is needed
  64. }
  65.  
  66. ////////////////////////////////////////////////////////////////////////////////////////////////////
  67. // <summary>    cLua new. </summary>
  68. //
  69. // <remarks>    Chris, 29/07/2012. </remarks>
  70. //
  71. // <param name="LS"> [in,out] Lua State. </param>
  72. //
  73. // <returns>    1 = true 0 = false. </returns>
  74. //
  75. // <comment>    To create the object we need a new function that can be called within
  76. //              lua to create a new object
  77. //              in this example as well I have create a vector which I push the new object onto
  78. //              since they are pointers it means that both lua and c++ manipulate the same object
  79. //              the only 2 issues at the moment is that obj1 = obj2 means obj1 == obj2 which
  80. //              is not really what I want to happen i believe a __luathing (i think __newindex)
  81. //              is needed to create a new object but with similar values as obj2
  82. //              im fairly sure thats what is how the = should work rather than making the both
  83. //              equal
  84. //              the other issue at the moment is that there is not proper clean up
  85. //              the gc will work and delete the reference in the lua memory but will not
  86. //              clean it from the myClasses stack so it will still have bad pointers on it
  87. //              so I need to sort out better clean up for that
  88. // </comment>
  89. ////////////////////////////////////////////////////////////////////////////////////////////////////
  90.  
  91. inline int cLua_new(lua_State* LS)
  92. {
  93.     //in this case I have allowed for 2 choices of new 1: new() and new(intvalue)
  94.     int arg = lua_gettop(LS); //so i need to check how many arguments have been sent to get the correct setting
  95.  
  96.     //val will store the values sent to new which will be used to create the object if value was specified
  97.     int val = 0;
  98.  
  99.     //check arguments
  100.     if (arg == 1)
  101.     {
  102.         val = lua_tointeger(LS, 1);
  103.     }
  104.  
  105.     //now this is the odd but that im not 100% sure about. it would make sense to me if it was a single poiter but its not
  106.     //in one of the websites it mentioned something about the CRT heap but again I have no idea what that is.
  107.     //I believe lua has an odd way of storing user data which can be accessed as a 2D array but I expect that we really only need
  108.     //a single pointer but lua will use the double pointer to store other bits of data but dont quote me on that I will have to look into it
  109.     cLua** uData = (cLua**)lua_newuserdata(LS, sizeof(cLua*));
  110.  
  111.     //check the value to see if a value was passed and if so we need to create the object with accordance to the parameters
  112.     if (val)
  113.         *uData = new cLua(val);
  114.     else
  115.         *uData = new cLua();
  116.  
  117.     //this will get the metatable luaL_cLua which has the reference to all the c functions that are in the luaL_cLua metatable (in this case our class cLua)
  118.     luaL_getmetatable(LS, "luaL_cLua");
  119.  
  120.     //will set the meta table to the newly created class
  121.     lua_setmetatable(LS, -2);
  122.  
  123.     //when the new class is created we also may want to manipulate it within c++ so better store a reference to it as well
  124.     //as iv mentioned at the start there is no clean up for this stack so when the pointer is deleted at the moment it will only
  125.     //destroy the lua refernce. to fix this I would add either an autogenerate uID or force the user to create a uID for the object
  126.     //then when the release of lua is called a cleanup of the vector is also needed;  
  127.     myClasses.push_back(*uData);
  128.  
  129.     return 1;
  130. }
  131.  
  132. ////////////////////////////////////////////////////////////////////////////////////////////////////
  133. // <summary>    cLua hello world. </summary>
  134. //
  135. // <remarks>    Chris, 29/07/2012. </remarks>
  136. //
  137. // <param name="LS"> [in,out] Lua State. </param>
  138. //
  139. // <returns>    1 = true 0 = false. </returns>
  140. //
  141. // <comment>    Nothing wrong with having a little helloworld
  142. //              this will call the helloworld function in the cLua class
  143. //              which prints out hello world
  144. // </comment>
  145. ////////////////////////////////////////////////////////////////////////////////////////////////////
  146.  
  147. inline int cLua_helloWorld(lua_State* LS)
  148. {
  149.     //get the cLua object
  150.     cLua* l_cLua = lua_iscLua(LS, 1);
  151.  
  152.     //call the hello world function
  153.     l_cLua->helloWorld();
  154.  
  155.     return 1;
  156. }
  157.  
  158. ////////////////////////////////////////////////////////////////////////////////////////////////////
  159. // <summary>    cLua getvalue. </summary>
  160. //
  161. // <remarks>    Chris, 29/07/2012. </remarks>
  162. //
  163. // <param name="LS"> [in,out] Lua State. </param>
  164. //
  165. // <returns>    1 = true 0 = false. </returns>
  166. //
  167. // <comment>    cLua has a int value variable which can be set and get. this is the get function
  168. //              which obtains value and pushes it onto the stack as a return
  169. // </comment>
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////
  171.  
  172. inline int cLua_getvalue(lua_State* LS)
  173. {
  174.     //get the cLua object
  175.     cLua* l_cLua = lua_iscLua(LS, 1);
  176.     //get value
  177.     int i = l_cLua->getvalue();
  178.     //push value onto the stack
  179.     lua_pushinteger(LS, i);
  180.  
  181.     return 1;
  182. }
  183.  
  184. ////////////////////////////////////////////////////////////////////////////////////////////////////
  185. // <summary>    cLua set array. </summary>
  186. //
  187. // <remarks>    Chris, 29/07/2012. </remarks>
  188. //
  189. // <param name="LS"> [in,out] Lua State. </param>
  190. //
  191. // <returns>    1 = true 0 = false. </returns>
  192. //
  193. // <comment>    This was to test if arrays could still be sent to classes as well
  194. //              since this will be important for vectors and other things I cant think of
  195. //              off the top of my head
  196. //              it looks complex but its exactly the same as with a non class table call
  197. // </comment>
  198. ////////////////////////////////////////////////////////////////////////////////////////////////////
  199.  
  200. inline int cLua_setArray(lua_State* LS)
  201. {
  202.     //cLua_dumpstack(LS);
  203.  
  204.     //get the cLua Object
  205.     cLua* l_cLua = lua_iscLua(LS, 1);
  206.  
  207.  
  208.     //preform the same function as with TestTable in LuaManager.cpp
  209.     int size;
  210.     int* Array;
  211.  
  212.     if(lua_istable(LS, 2)) //checks to see if the value is a table (table is at -1)
  213.     {
  214.         size = lua_objlen(LS, 2); //this will return the size of the table (or a string) to get the size
  215.         Array = new int[size]; //create a pointer array of that size
  216.  
  217.         lua_pushnil(LS);    //not really sure why nill is needed to be pushed but it is needed to traverse a table
  218.         //Lua_dumpstack(LS);
  219.         while(lua_next(LS, 2) != 0) //this will iterate through the table at -2 since nill has been pushed onto the stack so its table -2 nill -1
  220.         {
  221.             lua_pushvalue(LS, -2); //the value at -2 on the table is now pushed onto the stack so it should be table -2 key -1
  222.             //Lua_dumpstack(LS);
  223.             printf("LUA - index %d = %d \n", lua_tointeger(LS, -1) - 1, lua_tointeger(LS, -2)); //prints out the value and key of the table (change lua_tointeger to lua_tostring if you have alphanumerical keys and data
  224.             Array[lua_tointeger(LS, -1) - 1] = lua_tointeger(LS, -2); //stores the key and value into the array (lua table starts at 1 and not 0 so the key has to be offset by -1)
  225.             //Lua_dumpstack(LS);
  226.             lua_pop(LS, 2); //pop the key back off the stack i belive and move onto the next value
  227.             //Lua_dumpstack(LS);
  228.         }
  229.         lua_pop(LS, 2); //I believe this now pops the table off the stack as it is now un-needed
  230.     }
  231.     else
  232.         return 0;
  233.  
  234.     //then just set the array to the cLua object
  235.     l_cLua->SetArray(Array);
  236.  
  237.     return 1;
  238. }
  239.  
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////
  241. // <summary>    cLua set value. </summary>
  242. //
  243. // <remarks>    Chris, 29/07/2012. </remarks>
  244. //
  245. // <param name="LS"> [in,out] Lua State. </param>
  246. //
  247. // <returns>    1 = true 0 = false. </returns>
  248. //
  249. // <comment>    the setter for the cLua value variable
  250. // </comment>
  251. ////////////////////////////////////////////////////////////////////////////////////////////////////
  252.  
  253. inline int cLua_setValue(lua_State* LS)
  254. {
  255.     //get the cLua object
  256.     cLua* l_cLua = lua_iscLua(LS, 1);
  257.     //get the value of the stack
  258.     int value = lua_tointeger(LS, 2);
  259.     //set the value of the cLua Object
  260.     l_cLua->SetValue(value);
  261.     return 1;
  262. }
  263.  
  264. ////////////////////////////////////////////////////////////////////////////////////////////////////
  265. // <summary>    cLua release. </summary>
  266. //
  267. // <remarks>    Chris, 29/07/2012. </remarks>
  268. //
  269. // <param name="LS"> [in,out] Lua State. </param>
  270. //
  271. // <returns>    1 = true 0 = false. </returns>
  272. //
  273. // <comment>    this is the garbage collector for lua that will be called when cLua is null
  274. //              as iv mentioned twice now the vector will need to have its refernce of the object deleted
  275. //              as well other wise it will break the vector
  276. // </comment>
  277. ////////////////////////////////////////////////////////////////////////////////////////////////////
  278.  
  279. inline int cLua_Release(lua_State* LS)
  280. {
  281.  
  282.     cLua* l_cLua = lua_iscLua(LS, 1);
  283.     delete l_cLua;
  284.  
  285.     return 0;
  286. }
  287.  
  288. ////////////////////////////////////////////////////////////////////////////////////////////////////
  289. // <summary>    cLua bind. </summary>
  290. //
  291. // <remarks>    Chris, 29/07/2012. </remarks>
  292. //
  293. // <param name="LS"> [in,out] Lua State. </param>
  294. //
  295. // <comment>    this is the binding of the cLua Object to Lua
  296. // </comment>
  297. ////////////////////////////////////////////////////////////////////////////////////////////////////
  298.  
  299. inline void cLua_Bind(lua_State* LS)
  300. {
  301.     //create a reference for all the functions
  302.     //has to have null null at the end (expect it takes the array
  303.     //as a pointer so there is no real way of knowing the end of the array)
  304.     luaL_Reg cLua_Reg[] =
  305.     {
  306.         { "new",            cLua_new        },
  307.         { "helloWorld",     cLua_helloWorld },
  308.         { "setArray",       cLua_setArray   },
  309.         { "setValue",       cLua_setValue   },
  310.         { "getValue",       cLua_getvalue   },
  311.         { "__gc",           cLua_Release    },
  312.         { NULL,             NULL            },
  313.     };
  314.  
  315.     //create a new metatable which wont be visable to lua but is used to refernce the lua objects
  316.     luaL_newmetatable(LS, "luaL_cLua");
  317.  
  318.     //register the lua functions
  319.     luaL_register(LS, NULL, cLua_Reg);
  320.  
  321.     //this pushes the meta table onto the stack so __index can point to itself
  322.     lua_pushvalue(LS, -1);
  323.     lua_setfield(LS, -1, "__index");
  324.  
  325.     //sets the global name for the class object type
  326.     lua_setglobal(LS, "cLua");
  327.  
  328. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement