#include <stdio.h>
#include<iostream>
//g++ -g lua_api-new.cpp -I/usr/local/include /usr/local/lib/liblua.a
using namespace std;
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#define TRACE_TOP printf("top=%d\n",lua_gettop(L));
template <class T> class LuaMgr
{
public:
static void Register(lua_State *L)
{
//构造函数 放到全局中(实际中建议集中放到单独表内)
lua_pushcfunction(L, &LuaMgr <T>::constructor);
lua_setglobal(L, T::classname);
//建立元表
luaL_newmetatable(L, T::classname);
//设置垃圾回收
lua_pushstring(L, "__gc");
lua_pushcfunction(L, &LuaMgr <T>::gc_obj);
lua_rawset(L, -3);
//设置index
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);
lua_rawset(L, -3);
//设置类成员函数。 注意此部分的语法:function并没有直接声明在模板内
for (int i = 0; T::function[i].name; i++)
{
lua_pushstring(L, T::function[i].name);
lua_pushnumber(L, i); //upvalue
lua_pushcclosure(L, &LuaMgr<T>::thunk, 1);
lua_rawset(L, -3); //table["T::function[i].name"] = thunk;
}
}
static int constructor(lua_State *L) //构造函数返回表,该函数用于脚本调用
{
T* obj = new T(L); //实际建立一个对象。可采用共享内存
T** u = (T**)lua_newuserdata(L, sizeof(T*)); //获得一个指针
*u = obj;
//设置u元表
luaL_getmetatable(L, T::classname);
lua_setmetatable(L, -2);
return 1; //返回u
}
//该函数用于c层调用,创建对象。由于没有直接返回lua,而没有被引用,要防止被释放
static void* c_create(lua_State *L)
{
T* obj = new T(L); //实际建立一个对象。可采用共享内存
void** u = (void**)lua_newuserdata(L, sizeof(T*)); //获得一个指针
*u = obj;
//设置u元表
luaL_getmetatable(L, T::classname);
lua_setmetatable(L, -2);
lua_pop(L,1);
//最好存放在表内,防止在被释放,如放到全局lua_setglobal(L,"aaafff");
return u; //返回u
}
static int thunk(lua_State *L)
{
int i = (int)lua_tonumber(L, lua_upvalueindex(1));
T** obj = static_cast <T**>(luaL_checkudata(L, 1, T::classname));
return ((*obj)->*(T::function[i].mfunc))(L);
}
static int gc_obj(lua_State *L)
{
T** obj = static_cast <T**>(luaL_checkudata(L, -1, T::classname));
delete (*obj);
printf("deleteing\n");
return 0;
}
struct RegType
{
const char *name;
int(T::*mfunc)(lua_State*);
};
};
class Base
{
public:
Base() {}
~Base() {}
int add(int a, int b)
{
return a + b;
}
};
class Foo //:public Base
{
public:
Foo(lua_State *L) { printf("call Foo constructor\n"); }
~Foo() { printf("call Foo destructor\n"); }
int foo(lua_State *L) { printf("in foo function\n"); return 0; }
int n_add(lua_State *L)
{
int a = NULL;
int b = NULL;
a = (int)luaL_checknumber(L, -2);
b = (int)luaL_checknumber(L, -1);
double result = a+b;//add(a, b);
lua_pushnumber(L, result);
return 1;
}
/******************只需增加 ****************************************/
friend class LuaMgr <Foo>;
private:
static const LuaMgr <Foo>::RegType function[];
static const char classname[];
};
const char Foo::classname[] = "Foo";
const LuaMgr <Foo>::RegType Foo::function[] =
{
{ "foo", &Foo::foo},
{ "add_func", &Foo::n_add},
{ NULL , NULL}
};
/******************只需增加 end****************************************/
//驱动程序
int main()
{
lua_State *L = lua_open();
luaopen_base(L);
LuaMgr <Foo>::Register(L);
luaL_dofile(L, "t.lua");
//直接在c 内建立userdata.可以把该user传给lua,在lua内操作对象。lua_newuserdata 地址和lua对象(TValue值)是不同的
//创建时候,必须保存lua对象 ,直接压入地址不行 。可在lapi.h 内增加接口 TValue * luaA_getobject (lua_State *L,int indx ) {return index2adr(L, indx);}
//void** u = (void** )LuaMgr ::c_create(L); //
lua_close(L);
return 0;
}
|