lua是一个内嵌式的语言,很多初学者对于lua中使用c++类中的函数,或者用c++直接创建一个自己的自定义数据类型比较头疼,因为这部分确实比较乱,牵扯到内存释放分配等问题,但是如果把其中关系理清,还是很简单的,下面这段代码是一个老外写的,我做了一些修改。首先看代码。
以上是一个头文件,包含到代码中,直接就可以使用。
这段代码的用处是将一个c++类包装成lua中的自定义数据类型。
在类声明中要添加如 LUNA_CLASS_D_DEFAULT_VALS宏:
这个类实现了一个luaprint函数,他只会输出一个字符串。
在类声明的最后,要把这个宏加上,宏的第一个参数是类名,第二个参数是一个任意类型的指针,目前没用。
我们现在看看LUNA_CLASS_D_DEFAULT_VALS是什么
这个宏在类中添加了3个变量,其中m_pLink目前没用,className是一个字符串数组,用来保存类名,而Register是一个RegType类型的数组。
RegType是一个结构如下:
struct RegType {
const char *name;
int(T::*mfunc)(lua_State*);
};
这个结构保存一个c++类中的函数。他将在下面的部分进行初始化。
下面将要在类声明外进行刚刚那些变量的初始化工作,他们是由下面这些宏组成
LUNA_CLASS_D_INIT_VALS_CLASSNAME(aa,void)
LUNA_CLASS_D_INIT_VALS_FUNCNAME_START(aa)
LUNA_CLASS_D_INIT_VALS_FUNCNAME_USER(luaprint,aa)
LUNA_CLASS_D_INIT_VALS_FUNCNAME_END
首先LUNA_CLASS_D_INIT_VALS_CLASSNAME宏初始化m_pLink和className变量,而下面三个宏初始化RegType变量。
如果类中还有其他函数,并且他符合int(T::*mfunc)(lua_State*);的样式,那么就可以用LUNA_CLASS_D_INIT_VALS_FUNCNAME_USER添加进来。
那么,这个类就已经包装好,等待放到lua中。之所以说等待,是因为我们需要将这个类注册到lua中,好让lua知道,这样我们在lua中才能调用。
注册方法是,在程序启动的时候调用luna_register( ls, aa )宏。
其中ls是lua_state,aa是刚刚包装的类
至此,在lua中之需要下面这样,就可以轻松调用c函数了
local test = aa()
test:luaprint("123")
以上是这个luna模板最基本的应用
其他还有
LUNA_CLASS_D_INIT_VALS_FUNCNAME_ALIAS_USER用于将一个函数声明为其他名称,比如想实现lua中元表的__index函数:
LUNA_CLASS_D_INIT_VALS_FUNCNAME_ALIAS_USER(luaprint,aa,"__index")
这样,当任何对自定义函数的取值操作,都将调用luaprint函数,当然,如果不修改luaprint函数,结果肯定是错误的,__index函数必须返回一个值。
luna_register_singleton 宏用于注册一个Ogre::Singleton的派生类,一般用于lua访问c环境中全局唯一实例的类
BUILD_LUACLASS宏用于创建一个已经注册的类的新实例,并且放到当前堆栈中。
BUILD_LUACLASS_LP宏用于创建一个已经注册的类,其指针是c++提供,并且由c++释放。