#include <iostream>
#include <string>
#define LUA_LIB
#include <lua.hpp>
class
MyClass;
typedef
int
(MyClass::*cmtype)(lua_State* L);
#define METHOD(CLASS, METHODNAME) {#METHODNAME, &CLASS::METHODNAME}
class
MyClass {
public
:
struct
methods{
const
char
* name;
cmtype method;
};
static
char
ClassName[0x20];
public
:
static
int
Create(lua_State* L) {
MyClass** pobj;
static
struct
MyClass::methods methodtable[] = {
METHOD(MyClass, SumThem),
METHOD(MyClass, SetNumA),
METHOD(MyClass, SetNumB),
METHOD(MyClass, GetNumA),
METHOD(MyClass, GetNumB),
METHOD(MyClass, SetName),
METHOD(MyClass, GetName),
{NULL, NULL}
};
if
(lua_gettop(L) != 3)
return
0;
const
char
* name = luaL_checkstring(L, 1);
int
a = luaL_checkinteger(L, 2);
int
b = luaL_checkinteger(L, 3);
lua_settop(L, 0);
pobj = (MyClass**)lua_newuserdata(L,
sizeof
(MyClass**));
if
(pobj == NULL)
return
0;
try
{
*pobj =
new
MyClass(name, a, b);
}
catch
(...) {
return
0;}
int
userdata_index = lua_gettop(L);
lua_getglobal(L, MyClass::ClassName);
int
method_index = lua_gettop(L);
if
(lua_type(L, method_index) == LUA_TNIL) {
lua_newtable(L);
method_index = lua_gettop(L);
for
(
struct
MyClass::methods* p = ( MyClass::methods*)methodtable;
(p->name) && (p->method); p++) {
lua_pushstring(L, p->name);
lua_pushlightuserdata(L, p);
lua_pushcclosure(L, MyClass::Thunk, 1);
lua_settable(L, method_index);
}
lua_pushliteral(L,
"destroy"
);
lua_pushcfunction(L, MyClass::destroy);
lua_settable(L, method_index);
}
if
(luaL_newmetatable(L, ClassName) != 0) {
if
(luaL_getmetatable(L, ClassName) == 0)
return
1;
}
int
mtable_index = lua_gettop(L);
lua_pushliteral(L,
"__index"
);
lua_pushvalue(L, method_index);
lua_settable(L, mtable_index);
lua_pushliteral(L,
"__metatable"
);
lua_pushstring(L,
"就不让你知道,嘤嘤嘤~~~"
);
lua_settable(L, mtable_index);
lua_pushliteral(L,
"__gc"
);
lua_pushcfunction(L, MyClass::destroy);
lua_settable(L, mtable_index);
lua_pushliteral(L,
"__mode"
);
lua_pushliteral(L,
"kv"
);
lua_settable(L, mtable_index);
lua_pushvalue(L, mtable_index);
lua_setmetatable(L, userdata_index);
lua_settop(L, userdata_index);
return
1;
}
static
int
Thunk(lua_State* L) {
MyClass* o;
if
(MyClass::CheckPointer(L, &o) ==
false
)
return
0;
struct
MyClass::methods* p = (MyClass::methods*)lua_touserdata(L, lua_upvalueindex(1));
if
(!p) {
luaL_error(L,
"函数表出错!"
);
return
0;
}
lua_remove(L, 1);
return
(o->*(p->method))(L);
}
static
bool
CheckPointer(lua_State* L, MyClass** po)
{
MyClass** pobj;
if
(lua_gettop(L) == 0) {
luaL_error(L,
"参数错误!\n请用\":\"方式调用!"
);
return
false
;
}
if
(lua_type(L, 1) != LUA_TUSERDATA) {
luaL_error(L,
"调用方式错误!\n请用\":\"方式调用!"
);
return
false
;
}
pobj = (MyClass**)lua_touserdata(L, 1);
if
(pobj != NULL) {
if
((*po = *pobj) == NULL)
luaL_error(L,
"对象已销毁!"
);
return
true
;
}
else
{
luaL_error(L,
"内存已经被回收!"
);
return
false
;
}
}
static
int
destroy(lua_State* L) {
MyClass** pobj;
if
(lua_gettop(L) == 0) {
luaL_error(L,
"此函数无参数!请用\":\"方式调用!"
);
}
else
{
if
(lua_type(L, 1) == LUA_TUSERDATA) {
pobj = (MyClass**)lua_touserdata(L, 1);
if
(pobj != NULL) {
if
(*pobj != NULL) {
delete
*pobj;
*pobj = NULL;
}
else
{
luaL_error(L,
"对象已销毁!"
);
}
}
else
{
luaL_error(L,
"内存已经被回收!"
);
}
}
}
return
0;
}
~MyClass(
void
){
std::cout<<
"Goodbye, I'm "
<< *(
this
->name) <<
". MyClass was Destroyed!"
<< std::endl;
delete
this
->name;
};
int
SumThem(lua_State* L) {
lua_pushinteger(L,
this
->na +
this
->nb);
return
1;
}
int
SetNumA(lua_State* L) {
this
->na = luaL_checkinteger(L, 1);
return
0;
}
int
SetNumB(lua_State* L) {
this
->nb = luaL_checkinteger(L, 1);
return
0;
}
int
GetNumA(lua_State* L) {
lua_pushinteger(L,
this
->na);
return
1;
}
int
GetNumB(lua_State* L) {
lua_pushinteger(L,
this
->nb);
return
1;
}
int
GetName(lua_State* L) {
lua_pushstring(L,
this
->name->c_str());
return
1;
}
int
SetName(lua_State* L) {
const
char
* name = luaL_checkstring(L, 1);
delete
this
->name;
this
->name =
new
std::string(name);
return
1;
}
private
:
int
na, nb;
std::string* name;
MyClass(
const
char
* name,
int
a,
int
b):na(a),nb(b){
this
->name =
new
std::string(name);
std::cout<<
"Hello, I'm "
<< *(
this
->name) <<
". MyClass was Created!"
<< std::endl;
};
MyClass(
void
){}
};
char
MyClass::ClassName[0x20] = {
"{1111-2222-3333-4444}"
};
extern
"C"
__declspec
(
dllexport
)
int
luaopen_lbindthunk(lua_State* L)
{
lua_pushcfunction(L, MyClass::Create);
return
1;
}