将c++注册到lua
时间:2010-09-26 来源:wwm
今天看到一篇文章,介绍了c++到lua的注册,感觉不错。原文地址:http://topic.csdn.net/u/20080725/15/7b6a1be7-ad10-4410-abc2-3affcd81e8ff.html
#include <stdio.h>
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
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 = add(a, b);
lua_pushnumber(L, result);
return 1;
}
static const char classname[];
static const luna <Foo>::RegType function[];
};
/////////利用lua wipper//luaWipper.h////////////
template <class T> class Luna {
public:
static void Register(lua_State *L) {
lua_pushcfunction(L, &Luna <T>::constructor);
//注册函数,在lua中创建function类型的值来表示Luna <T>::constructor
//该函数并将类型为fucntion的值入栈
lua_setglobal(L, T::className);
//将上面的function值赋给全局变量T::className
//在这里是将该值赋给下面的“Foo”:const char Foo::className[] = "Foo";
luaL_newmetatable(L, T::className);
//创建一个新表(将用作metatable),将新表放到栈顶并建立表和registry中类型名的联系。
//这个关联是双向的:使用类型名作为表的key;
//同时使用表作为类型名的key(这种双向的关联,使得其他的两个函数的实现效率更高)。
lua_pushstring(L, "__gc");
/*
Lua以__gc元方法的方式提供了finalizers。这个元方法只对userdata类型的值有效。
当一个userdatum将被收集的时候,并且usedatum有一个__gc域,
Lua会调用这个域的值(应该是一个函数):以userdatum作为这个函数的参数调用。
这个函数负责释放与userdatum相关的所有资源。
*/
lua_pushcfunction(L, &Luna <T>::gc_obj);
lua_settable(L, -3);
}
static int constructor(lua_State *L) {
T* obj = new T(L);
lua_newtable(L);
lua_pushnumber(L, 0);
T** a = (T**)lua_newuserdata(L, sizeof(T*));
//void *lua_newuserdata (lua_State *L, size_t size);
*a = obj;
luaL_getmetatable(L, T::className);
//void luaL_getmetatable (lua_State *L, const char *tname);
//函数获取registry中的tname对应的metatable。
lua_setmetatable(L, -2);
//lua_setmetatable函数将表(get到的)出栈,并将其设置为给定位置(上面userdatum)对象的metatable。
lua_settable(L, -3); // table[0] = userdatum;即table[0] = obj
for (int i = 0; T::Register[i].name; i++) {
lua_pushstring(L, T::Register[i].name);
lua_pushnumber(L, i);
lua_pushcclosure(L, &Luna <T>::thunk, 1);
lua_settable(L, -3);
//table["T::Register[i].name"] = thunk;
}
return 1;
}
static int thunk(lua_State *L) {
int i = (int)lua_tonumber(L, lua_upvalueindex(1));
//当lua把C函数压入到堆栈里时会把参数存到updata里面,
//获取第一个upvalue到当前值
//函数lua_upvalueindex(实际是一个宏),用来产生一个upvalue 的假索引。
//这个假索引除了不在栈中之外,和其他的索引一样。
//表达式lua_upvalueindex(1)为第一个upvalue的索引。
lua_pushnumber(L, 0);
lua_gettable(L, 1);
T** obj = static_cast <T**>(luaL_checkudata(L, -1, T::className));
//luaL_checkudata检查在栈中指定位置的对象是否为带有给定名字的metatable的usertatum。
//如果对象不存在正确的metatable,返回NULL(或者它不是一个userdata);
//否则,返回userdata的地址。
lua_remove(L, -1);
return ((*obj)->*(T::Register[i].mfunc))(L);
//&foo
}
static int gc_obj(lua_State *L) {
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*);
//function pointer
};
};
///////////////////////////////luawipper.h end//////////////////////////////
const char Foo::classname[] = "Foo";
const luna <Foo>::RegType Foo::function[] =
{
{ "foo", &Foo::foo},
{ "add", &Foo::n_add},
{ NULL , NULL }
};
////////////////////test.lua////////////////
/*
local f = Foo()
f:foo()
print("add is:",f:add(5,6))
*/
////////////////////////////////////////////
//驱动程序
int main()
{
lua_State *L = lua_open();
luaopen_base(L);
luna <Foo>::Register(L);
luaL_dofile(L, "test.lua");
lua_close(L);
return 0;
}
#include <stdio.h>
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
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 = add(a, b);
lua_pushnumber(L, result);
return 1;
}
static const char classname[];
static const luna <Foo>::RegType function[];
};
/////////利用lua wipper//luaWipper.h////////////
template <class T> class Luna {
public:
static void Register(lua_State *L) {
lua_pushcfunction(L, &Luna <T>::constructor);
//注册函数,在lua中创建function类型的值来表示Luna <T>::constructor
//该函数并将类型为fucntion的值入栈
lua_setglobal(L, T::className);
//将上面的function值赋给全局变量T::className
//在这里是将该值赋给下面的“Foo”:const char Foo::className[] = "Foo";
luaL_newmetatable(L, T::className);
//创建一个新表(将用作metatable),将新表放到栈顶并建立表和registry中类型名的联系。
//这个关联是双向的:使用类型名作为表的key;
//同时使用表作为类型名的key(这种双向的关联,使得其他的两个函数的实现效率更高)。
lua_pushstring(L, "__gc");
/*
Lua以__gc元方法的方式提供了finalizers。这个元方法只对userdata类型的值有效。
当一个userdatum将被收集的时候,并且usedatum有一个__gc域,
Lua会调用这个域的值(应该是一个函数):以userdatum作为这个函数的参数调用。
这个函数负责释放与userdatum相关的所有资源。
*/
lua_pushcfunction(L, &Luna <T>::gc_obj);
lua_settable(L, -3);
}
static int constructor(lua_State *L) {
T* obj = new T(L);
lua_newtable(L);
lua_pushnumber(L, 0);
T** a = (T**)lua_newuserdata(L, sizeof(T*));
//void *lua_newuserdata (lua_State *L, size_t size);
*a = obj;
luaL_getmetatable(L, T::className);
//void luaL_getmetatable (lua_State *L, const char *tname);
//函数获取registry中的tname对应的metatable。
lua_setmetatable(L, -2);
//lua_setmetatable函数将表(get到的)出栈,并将其设置为给定位置(上面userdatum)对象的metatable。
lua_settable(L, -3); // table[0] = userdatum;即table[0] = obj
for (int i = 0; T::Register[i].name; i++) {
lua_pushstring(L, T::Register[i].name);
lua_pushnumber(L, i);
lua_pushcclosure(L, &Luna <T>::thunk, 1);
lua_settable(L, -3);
//table["T::Register[i].name"] = thunk;
}
return 1;
}
static int thunk(lua_State *L) {
int i = (int)lua_tonumber(L, lua_upvalueindex(1));
//当lua把C函数压入到堆栈里时会把参数存到updata里面,
//获取第一个upvalue到当前值
//函数lua_upvalueindex(实际是一个宏),用来产生一个upvalue 的假索引。
//这个假索引除了不在栈中之外,和其他的索引一样。
//表达式lua_upvalueindex(1)为第一个upvalue的索引。
lua_pushnumber(L, 0);
lua_gettable(L, 1);
T** obj = static_cast <T**>(luaL_checkudata(L, -1, T::className));
//luaL_checkudata检查在栈中指定位置的对象是否为带有给定名字的metatable的usertatum。
//如果对象不存在正确的metatable,返回NULL(或者它不是一个userdata);
//否则,返回userdata的地址。
lua_remove(L, -1);
return ((*obj)->*(T::Register[i].mfunc))(L);
//&foo
}
static int gc_obj(lua_State *L) {
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*);
//function pointer
};
};
///////////////////////////////luawipper.h end//////////////////////////////
const char Foo::classname[] = "Foo";
const luna <Foo>::RegType Foo::function[] =
{
{ "foo", &Foo::foo},
{ "add", &Foo::n_add},
{ NULL , NULL }
};
////////////////////test.lua////////////////
/*
local f = Foo()
f:foo()
print("add is:",f:add(5,6))
*/
////////////////////////////////////////////
//驱动程序
int main()
{
lua_State *L = lua_open();
luaopen_base(L);
luna <Foo>::Register(L);
luaL_dofile(L, "test.lua");
lua_close(L);
return 0;
}
相关阅读 更多 +
排行榜 更多 +










