一个使用c++在lua中创建自定义数据类型的简易方法

来源:互联网 发布:宿州淘宝招聘信息 编辑:程序博客网 时间:2024/05/16 12:05
luabind 

一个使用c++在lua中创建自定义数据类型的简易方法

分类: 游戏编程 1774人阅读 评论(0) 收藏 举报
luac++constructorclassfunctionbuild

lua是一个内嵌式的语言,很多初学者对于lua中使用c++类中的函数,或者用c++直接创建一个自己的自定义数据类型比较头疼,因为这部分确实比较乱,牵扯到内存释放分配等问题,但是如果把其中关系理清,还是很简单的,下面这段代码是一个老外写的,我做了一些修改。首先看代码。

 

[cpp] view plaincopy
  1. #ifndef LUNA_H  
  2. #define LUNA_H 1  
  3.   
  4.   
  5. /**************************************************************************** 
  6. * This program is free software. It comes without any warranty, to          * 
  7. * the extent permitted by applicable law. You can redistribute it           * 
  8. * and/or modify it under the terms of the Do What The Fuck You Want         * 
  9. * To Public License, Version 2, as published by Sam Hocevar. See            * 
  10. * http://sam.zoy.org/wtfpl/COPYING for more details.                        * 
  11. ****************************************************************************/  
  12.   
  13. /****************************************************************************** 
  14. * 这是一个自由传播修改的文件,如果你够厚道就保留下我的签名吧               * 
  15. * Edit by fox                                                                 * 
  16. * 2010-4-13                                                                   * 
  17. * http://blog.csdn.net/limiteee                                               * 
  18. ******************************************************************************/  
  19.   
  20. // convenience macros  
  21. //注册一个自定义类型,并用该类名创建一个元表  
  22. #define luna_register(L, klass) (Luna<klass>::Register((L)))  
  23.   
  24. //注册一个自定义数据类型,并用该类名创建一个元表,该类必须是一个Ogre::Singleton的派生类,一般用于lua访问c环境中全局唯一实例的类  
  25. #define luna_register_singleton(L, klass) (Luna<klass>::Register_singleton((L)))  
  26. #define luna_registermetatable(L, klass) (Luna<klass>::RegisterMetatable((L)))  
  27. #define luna_inject(L, klass, t) (Luna<klass>::inject((L), (t)))  
  28.   
  29. #define luna_flag_meta_func     0  
  30. #define luna_flag_func          1  
  31.   
  32.   
  33.   
  34. /* 
  35. ---------------------------------------------------------------------------------------------------------- 
  36. LUNA_CLASS_D_DEFAULT_VALS                           需要写在类声明中 
  37. LUNA_CLASS_D_INIT_VALS_CLASSNAME                    写在类实现中 
  38. LUNA_CLASS_D_INIT_VALS_FUNCNAME_START               开始进行lua声明,必须以这个宏开始 
  39. LUNA_CLASS_D_INIT_VALS_FUNCNAME_END                 lua声明结束,必须以这个宏结束 
  40. LUNA_CLASS_D_INIT_VALS_FUNCNAME_USER                进行用户自定义函数的lua声明 
  41. LUNA_CLASS_D_INIT_VALS_META_FUNCNAME_USER           定义一个元表的方法 
  42. LUNA_CLASS_D_INIT_VALS_META_FUNCNAME_ALIAS_USER     定义一个元表的方法,并且使用指定的别名 
  43.  
  44. BUILD_LUACLASS                                      在lua中创建一个指定类的自定义数据,new一个该类指针赋予这个自定义数据 
  45. BUILD_LUACLASS_LP                                   在lua中创建一个指定类的自定义数据,使用一个已经存在的该类指针赋予这个自定义数据 
  46.  
  47. cLinkName               可以是任何类,没有规定,这个类只是给lua类进行访问的。 
  48. cName                   是lua类,这个类将可以在lua中访问 
  49. ---------------------------------------------------------------------------------------------------------- 
  50. */  
  51.   
  52. #define LUNA_CLASS_D_DEFAULT_VALS(cName,cLinkName) /  
  53.     public: /  
  54.     static cLinkName *m_pLink; /  
  55.     static const char className[]; /  
  56.     static const Luna<cName>::RegType Register[];  
  57.   
  58.   
  59. #define LUNA_CLASS_D_INIT_VALS_CLASSNAME(cName,cLinkName) /  
  60.     cLinkName *cName::m_pLink = 0; /  
  61.     const char cName::className[] = #cName;  
  62. #define LUNA_CLASS_D_INIT_VALS_CLASSNAME_ALIAS(cName,cLinkName,Alias) /  
  63.     cLinkName *cName::m_pLink = 0; /  
  64.     const char cName::className[] = Alias;  
  65.   
  66. #define LUNA_CLASS_D_INIT_VALS_FUNCNAME_START(cName) /  
  67.     const Luna<cName>::RegType cName::Register[] = {  
  68.   
  69. #define  LUNA_CLASS_D_INIT_VALS_FUNCNAME_USER(fName,cName) /  
  70.     {#fName,&cName::fName},  
  71.   
  72. #define  LUNA_CLASS_D_INIT_VALS_FUNCNAME_ALIAS_USER(fName,cName,Alias) /  
  73.     {Alias,&cName::fName},  
  74.   
  75. #define LUNA_CLASS_D_INIT_VALS_FUNCNAME_END                 { 0 }};  
  76.   
  77. #define LUNA___INDEX_FUNCTION                       -1  
  78.   
  79. #define BUILD_LUACLASS(ClassName, L)                        Luna<ClassName>::constructor( L )  
  80. #define BUILD_LUACLASS_LP(ClassName, L, ClassPtr)           Luna<ClassName>::constructor_lightptr( L, ClassPtr );  
  81. //  
  82. //extern "C" {  
  83. //#include "lua.h"  
  84. //#include "lualib.h"  
  85. //#include "lauxlib.h"  
  86. //}  
  87. #include "lua.hpp"  
  88.   
  89. template<class T> class Luna {  
  90. public:  
  91.     //注册唯一实例的对象------------------------------------------------------------------------------------------------------------------------------------------------  
  92.     static void Register_singleton(lua_State *L) {  
  93.         const char* cn = T::className;  
  94.         lua_pushcfunction(L, &Luna<T>::constructor_singleton);  
  95.         lua_setglobal(L, T::className); // T() in lua will make a new instance.  
  96.     }  
  97.     //使用一个c环境中已存在的指针创建一个自定义数据,该指针需要c来释放,这个方法没有注册gc函数  
  98.     static int constructor_lightptr(lua_State *L, T* obj) {  
  99.         return inject_singleton(L, obj);  
  100.     }  
  101.     //使用一个Ogre::Singleton的派生类的指针创建一个自定义数据,该指针需要c来释放,这个方法没有注册gc函数  
  102.     static int constructor_singleton(lua_State *L) {  
  103.         return inject_singleton(L, static_cast<T*>(T::getSingletonPtr()));  
  104.     }  
  105.     static int inject_singleton(lua_State *L, T* obj) {  
  106.         //创建一个自定义数据,返回一个指向指针的指针,这里不使用light udata是因为我们需要lua为我们管理内存回收  
  107.         T** a = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));  
  108.         *a = obj; // 指针的指针赋值  
  109.   
  110.         const char *cn = T::className;  
  111.   
  112.         int rt = luaL_newmetatable(L, T::className); // get (or create) the unique metatable  
  113.   
  114.         if ( rt )  
  115.         {  
  116.             //设置一个默认的__index函数  
  117.             lua_pushstring(L, "__index");  
  118.             lua_pushnumber(L, LUNA___INDEX_FUNCTION);  
  119.             lua_pushcclosure(L, &Luna<T>::thunk, 1);  
  120.             lua_settable(L, -3);  
  121.   
  122.             //-----------------------------------------------------------------------  
  123.             //为元表添加方法  
  124.   
  125.             for (int i = 0; T::Register[i].name; i++) { // register the functions  
  126.                 lua_pushstring(L, T::Register[i].name);  
  127.                 lua_pushnumber(L, i); // let the thunk know which method we mean  
  128.                 lua_pushcclosure(L, &Luna<T>::thunk, 1);  
  129.                 lua_settable(L, -3); // self["function"] = thunk("function")  
  130.             }  
  131.         }  
  132.   
  133.         //-----------------------------------------------------------------------  
  134.         lua_setmetatable(L, -2); //将自定义数据的元表设置为刚刚创建的表  
  135.   
  136.         return 1;  
  137.     }  
  138.   
  139.     //这里注册可自动回收的对象---------------------------------------------------------------------------------------------------------------------  
  140.     static void Register(lua_State *L) {  
  141.         const char* cn = T::className;  
  142.         lua_pushcfunction(L, &Luna<T>::constructor);  
  143.         lua_setglobal(L, T::className); // T() in lua will make a new instance.  
  144.     }  
  145.   
  146.     static int constructor(lua_State *L) {  
  147.         return inject(L, new T(L));  
  148.     }  
  149.     static int inject(lua_State *L, T* obj) {  
  150.         //创建一个自定义数据,返回一个指向指针的指针,这里不使用light udata是因为我们需要lua为我们管理内存回收  
  151.         T** a = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));  
  152.         *a = obj; // 指针的指针赋值  
  153.   
  154.         const char *cn = T::className;  
  155.   
  156.         int rt = luaL_newmetatable(L, T::className); // get (or create) the unique metatable  
  157.   
  158.         if ( rt )  
  159.         {  
  160.             //设置一个默认的__index函数  
  161.             lua_pushstring(L, "__index");  
  162.             lua_pushnumber(L, LUNA___INDEX_FUNCTION);  
  163.             lua_pushcclosure(L, &Luna<T>::thunk, 1);  
  164.             lua_settable(L, -3);  
  165.   
  166.             //设置自动销毁函数  
  167.             lua_pushstring(L, "__gc");  
  168.             lua_pushcfunction(L, &Luna<T>::gc_obj);  
  169.             lua_settable(L, -3); // metatable["__gc"] = Luna<T>::gc_obj  
  170.             //-----------------------------------------------------------------------  
  171.             //为元表添加方法  
  172.   
  173.             for (int i = 0; T::Register[i].name; i++) { // register the functions  
  174.                 lua_pushstring(L, T::Register[i].name);  
  175.                 lua_pushnumber(L, i); // let the thunk know which method we mean  
  176.                 lua_pushcclosure(L, &Luna<T>::thunk, 1);  
  177.                 lua_settable(L, -3); // self["function"] = thunk("function")  
  178.             }  
  179.         }  
  180.   
  181.         //-----------------------------------------------------------------------  
  182.         lua_setmetatable(L, -2); //将自定义数据的元表设置为刚刚创建的表  
  183.   
  184.         return 1;  
  185.     }  
  186.     static int thunk(lua_State *L) {  
  187.         // redirect method call to the real thing  
  188.         int d = lua_gettop(L);  
  189.         int i = (int)lua_tonumber(L, lua_upvalueindex(1)); // which function?  
  190.         T** obj = static_cast<T**>(luaL_checkudata(L, 1, T::className));  //第一个参数就是他自己  
  191.   
  192.         //察看第二个参数是什么  
  193.         int iType = lua_type(L, 2);  
  194.   
  195.         if (iType == LUA_TSTRING) {  
  196.             //如果第二个参数是字符型,那么它可能是一个call调用  
  197.             int rt = call_obj(L);  
  198.             //如果调用发现同名函数那么执行它,并且返回  
  199.             if ( rt ) {  
  200.                 return rt;  
  201.             }  
  202.         }  
  203.   
  204.         //每次调用使用的是目标对象来调用,所以函数访问的内部变量就是他自己的  
  205.         return ((*obj)->*(T::Register[i].mfunc))(L); // execute the thunk  
  206.     }  
  207.     static int call_obj(lua_State *L) {  
  208.         int d = lua_gettop(L);  
  209.         T** obj = static_cast<T**>(luaL_checkudata(L, 1, T::className));  //第一个参数就是他自己  
  210.         const char* funcname = lua_tostring(L, 2);  
  211.         for (int i = 0; T::Register[i].name; i++) {  
  212.             if( strcmp( funcname, T::Register[i].name ) == 0 ) {  
  213.                 //找到这个函数,并且返回它  
  214.                 lua_pushnumber(L, i); // let the thunk know which method we mean  
  215.                 lua_pushcclosure(L, &Luna<T>::thunk, 1);  
  216.                 return 1;  
  217.             }  
  218.         }  
  219.         return 0;  
  220.     }  
  221.     static int gc_obj(lua_State *L) {  
  222.         // clean up  
  223.         //printf("GC called: %s/n", T::className);  
  224.         T** obj = static_cast<T**>(luaL_checkudata(L, -1, T::className));  
  225.         delete (*obj);  
  226.         return 0;  
  227.     }  
  228.   
  229.     struct RegType {  
  230.         const char *name;  
  231.         int(T::*mfunc)(lua_State*);  
  232.     };  
  233. };  
  234.   
  235.   
  236. #endif /* LUNA_H */  

0 0
原创粉丝点击