您的位置:首页 > 编程语言 > Lua

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

2014-01-23 13:25 891 查看
luabind


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

分类: 游戏编程2010-04-15
20:12 1774人阅读 评论(0) 收藏 举报

luac++constructorclassfunctionbuild

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



[cpp] view
plaincopy

#ifndef LUNA_H

#define LUNA_H 1





/****************************************************************************

* This program is free software. It comes without any warranty, to *

* the extent permitted by applicable law. You can redistribute it *

* and/or modify it under the terms of the Do What The Fuck You Want *

* To Public License, Version 2, as published by Sam Hocevar. See *

* http://sam.zoy.org/wtfpl/COPYING for more details. *

****************************************************************************/



/******************************************************************************

* 这是一个自由传播修改的文件,如果你够厚道就保留下我的签名吧 *

* Edit by fox *

* 2010-4-13 *

* http://blog.csdn.net/limiteee *

******************************************************************************/



// convenience macros

//注册一个自定义类型,并用该类名创建一个元表

#define luna_register(L, klass) (Luna<klass>::Register((L)))



//注册一个自定义数据类型,并用该类名创建一个元表,该类必须是一个Ogre::Singleton的派生类,一般用于lua访问c环境中全局唯一实例的类

#define luna_register_singleton(L, klass) (Luna<klass>::Register_singleton((L)))

#define luna_registermetatable(L, klass) (Luna<klass>::RegisterMetatable((L)))

#define luna_inject(L, klass, t) (Luna<klass>::inject((L), (t)))



#define luna_flag_meta_func 0

#define luna_flag_func 1







/*

----------------------------------------------------------------------------------------------------------

LUNA_CLASS_D_DEFAULT_VALS 需要写在类声明中

LUNA_CLASS_D_INIT_VALS_CLASSNAME 写在类实现中

LUNA_CLASS_D_INIT_VALS_FUNCNAME_START 开始进行lua声明,必须以这个宏开始

LUNA_CLASS_D_INIT_VALS_FUNCNAME_END lua声明结束,必须以这个宏结束

LUNA_CLASS_D_INIT_VALS_FUNCNAME_USER 进行用户自定义函数的lua声明

LUNA_CLASS_D_INIT_VALS_META_FUNCNAME_USER 定义一个元表的方法

LUNA_CLASS_D_INIT_VALS_META_FUNCNAME_ALIAS_USER 定义一个元表的方法,并且使用指定的别名



BUILD_LUACLASS 在lua中创建一个指定类的自定义数据,new一个该类指针赋予这个自定义数据

BUILD_LUACLASS_LP 在lua中创建一个指定类的自定义数据,使用一个已经存在的该类指针赋予这个自定义数据



cLinkName 可以是任何类,没有规定,这个类只是给lua类进行访问的。

cName 是lua类,这个类将可以在lua中访问

----------------------------------------------------------------------------------------------------------

*/



#define LUNA_CLASS_D_DEFAULT_VALS(cName,cLinkName) /

public: /

static cLinkName *m_pLink; /

static const char className[]; /

static const Luna<cName>::RegType Register[];





#define LUNA_CLASS_D_INIT_VALS_CLASSNAME(cName,cLinkName) /

cLinkName *cName::m_pLink = 0; /

const char cName::className[] = #cName;

#define LUNA_CLASS_D_INIT_VALS_CLASSNAME_ALIAS(cName,cLinkName,Alias) /

cLinkName *cName::m_pLink = 0; /

const char cName::className[] = Alias;



#define LUNA_CLASS_D_INIT_VALS_FUNCNAME_START(cName) /

const Luna<cName>::RegType cName::Register[] = {



#define LUNA_CLASS_D_INIT_VALS_FUNCNAME_USER(fName,cName) /

{#fName,&cName::fName},



#define LUNA_CLASS_D_INIT_VALS_FUNCNAME_ALIAS_USER(fName,cName,Alias) /

{Alias,&cName::fName},



#define LUNA_CLASS_D_INIT_VALS_FUNCNAME_END { 0 }};



#define LUNA___INDEX_FUNCTION -1



#define BUILD_LUACLASS(ClassName, L) Luna<ClassName>::constructor( L )

#define BUILD_LUACLASS_LP(ClassName, L, ClassPtr) Luna<ClassName>::constructor_lightptr( L, ClassPtr );

//

//extern "C" {

//#include "lua.h"

//#include "lualib.h"

//#include "lauxlib.h"

//}

#include "lua.hpp"



template<class T> class Luna {

public:

//注册唯一实例的对象------------------------------------------------------------------------------------------------------------------------------------------------

static void Register_singleton(lua_State *L) {

const char* cn = T::className;

lua_pushcfunction(L, &Luna<T>::constructor_singleton);

lua_setglobal(L, T::className); // T() in lua will make a new instance.

}

//使用一个c环境中已存在的指针创建一个自定义数据,该指针需要c来释放,这个方法没有注册gc函数

static int constructor_lightptr(lua_State *L, T* obj) {

return inject_singleton(L, obj);

}

//使用一个Ogre::Singleton的派生类的指针创建一个自定义数据,该指针需要c来释放,这个方法没有注册gc函数

static int constructor_singleton(lua_State *L) {

return inject_singleton(L, static_cast<T*>(T::getSingletonPtr()));

}

static int inject_singleton(lua_State *L, T* obj) {

//创建一个自定义数据,返回一个指向指针的指针,这里不使用light udata是因为我们需要lua为我们管理内存回收

T** a = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));

*a = obj; // 指针的指针赋值



const char *cn = T::className;



int rt = luaL_newmetatable(L, T::className); // get (or create) the unique metatable



if ( rt )

{

//设置一个默认的__index函数

lua_pushstring(L, "__index");

lua_pushnumber(L, LUNA___INDEX_FUNCTION);

lua_pushcclosure(L, &Luna<T>::thunk, 1);

lua_settable(L, -3);



//-----------------------------------------------------------------------

//为元表添加方法



for (int i = 0; T::Register[i].name; i++) { // register the functions

lua_pushstring(L, T::Register[i].name);

lua_pushnumber(L, i); // let the thunk know which method we mean

lua_pushcclosure(L, &Luna<T>::thunk, 1);

lua_settable(L, -3); // self["function"] = thunk("function")

}

}



//-----------------------------------------------------------------------

lua_setmetatable(L, -2); //将自定义数据的元表设置为刚刚创建的表



return 1;

}



//这里注册可自动回收的对象---------------------------------------------------------------------------------------------------------------------

static void Register(lua_State *L) {

const char* cn = T::className;

lua_pushcfunction(L, &Luna<T>::constructor);

lua_setglobal(L, T::className); // T() in lua will make a new instance.

}



static int constructor(lua_State *L) {

return inject(L, new T(L));

}

static int inject(lua_State *L, T* obj) {

//创建一个自定义数据,返回一个指向指针的指针,这里不使用light udata是因为我们需要lua为我们管理内存回收

T** a = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));

*a = obj; // 指针的指针赋值



const char *cn = T::className;



int rt = luaL_newmetatable(L, T::className); // get (or create) the unique metatable



if ( rt )

{

//设置一个默认的__index函数

lua_pushstring(L, "__index");

lua_pushnumber(L, LUNA___INDEX_FUNCTION);

lua_pushcclosure(L, &Luna<T>::thunk, 1);

lua_settable(L, -3);



//设置自动销毁函数

lua_pushstring(L, "__gc");

lua_pushcfunction(L, &Luna<T>::gc_obj);

lua_settable(L, -3); // metatable["__gc"] = Luna<T>::gc_obj

//-----------------------------------------------------------------------

//为元表添加方法



for (int i = 0; T::Register[i].name; i++) { // register the functions

lua_pushstring(L, T::Register[i].name);

lua_pushnumber(L, i); // let the thunk know which method we mean

lua_pushcclosure(L, &Luna<T>::thunk, 1);

lua_settable(L, -3); // self["function"] = thunk("function")

}

}



//-----------------------------------------------------------------------

lua_setmetatable(L, -2); //将自定义数据的元表设置为刚刚创建的表



return 1;

}

static int thunk(lua_State *L) {

// redirect method call to the real thing

int d = lua_gettop(L);

int i = (int)lua_tonumber(L, lua_upvalueindex(1)); // which function?

T** obj = static_cast<T**>(luaL_checkudata(L, 1, T::className)); //第一个参数就是他自己



//察看第二个参数是什么

int iType = lua_type(L, 2);



if (iType == LUA_TSTRING) {

//如果第二个参数是字符型,那么它可能是一个call调用

int rt = call_obj(L);

//如果调用发现同名函数那么执行它,并且返回

if ( rt ) {

return rt;

}

}



//每次调用使用的是目标对象来调用,所以函数访问的内部变量就是他自己的

return ((*obj)->*(T::Register[i].mfunc))(L); // execute the thunk

}

static int call_obj(lua_State *L) {

int d = lua_gettop(L);

T** obj = static_cast<T**>(luaL_checkudata(L, 1, T::className)); //第一个参数就是他自己

const char* funcname = lua_tostring(L, 2);

for (int i = 0; T::Register[i].name; i++) {

if( strcmp( funcname, T::Register[i].name ) == 0 ) {

//找到这个函数,并且返回它

lua_pushnumber(L, i); // let the thunk know which method we mean

lua_pushcclosure(L, &Luna<T>::thunk, 1);

return 1;

}

}

return 0;

}

static int gc_obj(lua_State *L) {

// clean up

//printf("GC called: %s/n", T::className);

T** obj = static_cast<T**>(luaL_checkudata(L, -1, T::className));

delete (*obj);

return 0;

}



struct RegType {

const char *name;

int(T::*mfunc)(lua_State*);

};

};





#endif /* LUNA_H */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐