原文:http://blog.csdn.net/chenee543216/article/details/12074771
以下是代码:
Animal.h文件
#pragma once
#ifndef __ANIMAL_H__
#define __ANIMAL_H__
class Animal
{
public:
Animal( const char *name );
void setAge( int age );
int getAge();
void sound();
~Animal(void);
private:
const char *name;
int age;
};
#endif
Animal.cpp文件
#include "stdafx.h"
#include "Animal.h"
Animal::Animal( const char* name ):age(0)
{
this->name = name;
}
Animal::~Animal(void)
{
printf( "Animal destructor." );
}
void Animal::setAge( int age )
{
this->age = age;
}
int Animal::getAge()
{
return this->age;
}
void Animal::sound()
{
printf("--Animal-- name: %s, age:%d\n", this->name, this->age );
}
LuaAimal.h
#pragma once
#ifndef __LUA_ANIMAL__
#define __LUA_ANIMAL__
class Animal;
class LuaAnimal
{
public:
~LuaAnimal(void);
static void Register( lua_State *l );
private:
static const char *className;
static const luaL_reg methods[];
static const luaL_reg methods_f[];
static int create( lua_State *l );
static int gc_animal( lua_State *l );
static Animal *getAnimal( lua_State *l );
static int sound( lua_State *l );
static int setAge(lua_State *l);
static int getAge(lua_State *l);
};
#endif
LuaAnimal.cpp
#include "stdafx.h"
#include "LuaAnimal.h"
#include "Animal.h"
#include "Utlis.h"
const char *LuaAnimal::className = "Animal";
const luaL_reg LuaAnimal::methods[] = {
{"sound", LuaAnimal::sound },
{"setAge", LuaAnimal::setAge},
{"getAge", LuaAnimal::getAge},
{"__gc", LuaAnimal::gc_animal},
{NULL,NULL}
};
const luaL_reg LuaAnimal::methods_f[] = {
{ "create", LuaAnimal::create },
{ NULL, NULL}
};
LuaAnimal::~LuaAnimal(void)
{
}
void LuaAnimal::Register( lua_State *l )
{
//1. new method table for l to save functions
lua_newtable(l);
int methodTable = lua_gettop(l);
//2.new metatable for L to save "__metatable", "__index", "__gc", etc
luaL_newmetatable(l, className );
int metaTable = lua_gettop(l);
//3.0 metatable["__metatable"] = methodtable;
lua_pushliteral( l, "__metatable" ); //remove \0
lua_pushvalue( l, methodTable );
lua_settable( l, metaTable );
//4.0 metatable["__index"] = methodtable
lua_pushliteral( l, "__index" );
lua_pushvalue( l, methodTable );
lua_rawset( l, metaTable ); // the same as lua_settable(1,metatable)
//5.0 metatable["__gc"] = gc_animal //will be called when lua_close(l)
lua_pushliteral( l, "__gc" );
lua_pushcfunction( l, LuaAnimal::gc_animal );
lua_rawset( l, metaTable );
lua_pop(l,1); //drop metatable
/*6.0 for object
name -- null set object funtion to methodtable( the table on top );
eg: Animal a = Animal("xxx")
a:func in this methodtable
fill methodtable, is libname is not null,
will create a table use the libname and push the table to stack*/
luaL_openlib( l, NULL, methods, 0 );
lua_pop(l,1); //drop methodtable
/*7.1 for class:
name = className, so this set function to "method_f"
eg: Animal a = Animal:create( "xx" );
Animal:create() in this method_f tables
*/
luaL_openlib( l, className, methods_f, 0 ); //push table[className] to stack
lua_pop(l,1); //drop table[className]
/*7.2 for class:
add global function "className", so we Animal() is a global function now
eg: Animal a = Animal("xx")
function Animal() in lua will call create in C++
*/
//lua_register(l, className, LuaAnimal::create );
}
int LuaAnimal::create( lua_State *l )
{
const char*name = lua_tostring(l,-1);
Animal *a = new Animal(name);
void **p = (void**)lua_newuserdata( l, sizeof(void*));
*p = a;
luaL_getmetatable( l, className );
lua_setmetatable( l, -2 );
return 1;
}
Animal* LuaAnimal::getAnimal( lua_State *l )
{
luaL_checktype( l, 1, LUA_TUSERDATA ); //indicate what type to check
void *ud = luaL_checkudata( l, 1, className );
if( !ud )
luaL_typerror( l, 1, className );
return *(Animal**)ud;
}
int LuaAnimal::gc_animal( lua_State *l )
{
Utlis::stackDump(l);
Animal *a = (Animal*)(*(void**)lua_touserdata(l,-1));
delete a;
return 0;
}
int LuaAnimal::getAge( lua_State *l )
{
Animal *a = getAnimal(l);
lua_pushinteger(l, a->getAge());
return 1;
}
int LuaAnimal::setAge( lua_State *l )
{
Animal *a = getAnimal(l);
int age = luaL_checkint(l,2);
a->setAge( age );
return 0;
}
int LuaAnimal::sound( lua_State *l )
{
Animal *a = getAnimal(l);
a->sound();
return 0;
}
工具类Utils,使用查看lua堆栈情况
Utils.h
#pragma once
#ifndef __UTLIS_H__
#define __UTLIS_H__
class Utlis
{
public:
Utlis(void);
~Utlis(void);
static void stackDump( lua_State *l );
};
#endif
Utils.cpp
#include "stdafx.h"
#include "Utlis.h"
Utlis::Utlis(void)
{
}
Utlis::~Utlis(void)
{
}
void Utlis::stackDump( lua_State *l )
{
int i;
int top = lua_gettop( l );
printf("------start-----%d\n", top);
for( i = 1; i <= top; i++ )
{
int t = lua_type( l, i );
printf("type: %s value:", lua_typename(l,t));
switch (t)
{
case LUA_TSTRING:
printf("%s", lua_tostring(l,i));
break;
case LUA_TBOOLEAN:
printf( lua_toboolean(l,i)? "true" : "false" );
break;
case LUA_TNUMBER:
printf("%g", lua_tonumber(l,i));
break;
default:
printf("%s", lua_typename(l,t));
break;
}
printf("\n");
}
printf("------end----\n" );
}
lua测试代码
main.lua
print( "test lua access C++ class" )
local function main()
--使用luaL_openlib( l, className, methods_f, 0 )注册,
--Animal是个table, 调用create方法
--local s = Animal.create("xx") --lua_gettop()=1 1:xx
local s = Animal:create("xx") --lua_gettop()=2 1:table, 2:xx, 相比.create多了一个table,指Animal本身
s:setAge(100)
s:sound()
--使用lua_register(l, className, LuaAnimal::create )注册
--Animal是个函数,直接调用方法
--local a = Animal("ww")
--a:setAge(20)
--a:sound()
end
main()
最后是C++测试代码
main.cpp
// TestLua.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Utlis.h"
#include "LuaAnimal.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
lua_State *l = lua_open();
luaL_openlibs(l);
LuaAnimal::Register(l);
Utlis::stackDump(l);
if( luaL_dofile( l, "main.lua" )){ // load and call
Utlis::stackDump(l);
}
Utlis::stackDump(l);
system("pause");
lua_close(l);
return 0;
}