一个使用c++在lua中创建自定义数据类型的简易方法
2014-01-23 13:25
891 查看
luabind
分类: 游戏编程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 */
一个使用c++在lua中创建自定义数据类型的简易方法
分类: 游戏编程2010-04-1520: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 */
相关文章推荐
- 一个使用c++在lua中创建自定义数据类型的简易方法
- C++库研究笔记——使用函数模板还是类模板?+ 一个类型重复问题的两种解决方法
- 使用Object对象的toString()方法自定义判断数据类型方法
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- 利用sqlite创建一个数据user,其含有一张表person,该person表中含有三个列,其中第一字段为主键int类型的,其他两个字段自定义数据类型和名称。
- C/C++ 数据类型的使用方法详解
- 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)
- 数组型队列(queue)的使用(支持自定义数据类型)(C++版)
- 创建一个调用lua方法的C++工程
- 使用MFC的CArray自定义数据类型,编译报错的解决方法
- Java parseInt_使用此方法得到的原始数据类型的一个特定的字符串
- 自学C++之自定义数据类型与自定义类之数组使用4例
- 一个使用泛型堆栈模块创建的两个容纳不同类型数据的实例
- C++ STL 有关于SET集合部分 的自定义数据类型的排序 以及 pair的使用
- ECMAScript中使用最广泛,认同度最高的一种创建自定义类型的方法
- C++中提供了多种基本的数据类型。实际上,这些远不能满足我们的需求,如复数(第10章的例子大多是处理虚数的),再如分数。本任务将设计一个简单的分数类,完成对分数的几个运算。一则巩固基于对象编程的方法,
- 一个自定义数据类型,教你使用索引器
- CryENGINE3初探Entities (一)----使用Lua创建一个自定义Entity并为其添加节点
- 使用系统方法 创建一个 自定义样式的button
- 为创建的一个自定义数据类型进行运算符重载