tolua++的代码看起来还是很舒服的(似乎看过linux源码之后,觉得别的代码都很亲近),模仿它写了一段时间,基本的框架出来了,这也是我想要的。先存个档吧。目前的demo是编译成dll用。、
mklua.h
-
#include"mklua.h"
-
#include"mklua_event.h"
-
-
/*
-
* 有个疑问,不是变成dll让lua用,而是从c++里开启lua,这里的lua_push用的
-
* 是哪里的vstack?
-
* BUG:这里注册到全局表的Dog找不到
-
*/
-
void begin_class_tbl(lua_State *L, char *class_name){
-
luaL_newmetatable(L, class_name); /*stack: mt*/
-
lua_newtable(L); /*stack: mt tbl */
-
lua_setfield(L, -2, "getter"); /*stack: mt*/
-
lua_newtable(L); /*stack: mt tbl*/
-
lua_setfield(L, -2, "setter"); /*stack: mt*/
-
lua_newtable(L); /*stack: mt ubox*/
-
lua_setfield(L, -2, "ubox"); /*stack: mt */
-
}
-
-
/*
-
* stack: mt
-
*/
-
void end_class_tbl(lua_State *L){
-
lua_pushstring(L, "__index");
-
lua_pushcfunction(L, on_index);
-
lua_rawset(L, -3);
-
lua_pushstring(L, "__newindex");
-
lua_pushcfunction(L, on_newindex);
-
lua_rawset(L, -3);
-
}
-
-
/*1, 像这种lua调用的c再调用的函数,应该是沿用母栈,没有自己的vstack,所
-
* 以,它在vstack上不能留痕迹。
-
*2, stack: mt
-
*/
-
void mklua_member(lua_State *L, char *member, lua_CFunction get_it, lua_CFunction set_it){
-
int ebp = lua_gettop(L);
-
-
lua_getfield(L, -1, "getter"); /*stack: mt getter */
-
lua_pushcfunction(L, get_it); /*stack: mt getter get_it */
-
lua_setfield(L, -2, member); /*stack: mt getter */
-
-
lua_getfield(L, -2, "setter"); /*stack: mt getter setter */
-
lua_pushcfunction(L, set_it); /*stack:mt gttr sttr set_it */
-
lua_setfield(L, -2, member); /*stack: mt gttr sttr */
-
-
lua_settop(L, ebp);
-
}
-
-
/*
-
* 0,直接把func挂到metatable上
-
* 1,stack: mt
-
*/
-
void mklua_function(lua_State *L, char *name, lua_CFunction func){
-
lua_pushcfunction(L, func);
-
lua_setfield(L, -2, name);
-
}
-
-
-
/*push ubox.lightu, 也就是以c实例为key,在ubox里找到(找不到就new一个
-
* )对应的userdata,并push到栈里*/
-
void mklua_pushusertype(lua_State *L, void *cobj, const char *class_name){
-
luaL_getmetatable(L, class_name); /*stack: mt */
-
if(lua_isnil(L, -1)){
-
printf("can not find class in registry\n");
-
return;
-
}
-
lua_getfield(L, -1, "ubox"); /*stack: mt ubox*/
-
if(lua_isnil(L, -1)){
-
printf("can not find ubox in mt\n");
-
return;
-
}
-
lua_pushlightuserdata(L, cobj); /*stack: mt ubox lu */
-
lua_rawget(L, -2); /*stack: mt ubox ubox.lu*/
-
if(lua_isnil(L, -1)){
-
printf("ubox.u not found, create a userdata and map it\n");
-
lua_pop(L, 1);
-
lua_pushlightuserdata(L, cobj); /*stack:mt ubox u */
-
lua_newuserdata(L, sizeof(void *)); /*stack: mt ubox u ud*/
-
-
/*下面这两句,只是为了把newud保存到栈底,不然rawset就没有了*/
-
lua_pushvalue(L, -1); /*stack: mt ubox u ud ud*/
-
lua_insert(L, -5); /*stack: ud mt ubox u ud */
-
-
lua_rawset(L, -3); /*stack: ud mt ubox*/
-
lua_pop(L, 1); /*stack: ud mt*/
-
lua_setmetatable(L, -2); /*stack: ud*/
-
return;
-
}
-
/*底下这一段跟上面的有重复代码,TODO*/
-
else lua_insert(L, -3); /*stack: ubox.lu mt ubox */
-
lua_pop(L, 1);
-
lua_setmetatable(L, -2); /*stack: newud */
-
return;
-
}
mklua_event.h
-
/*
-
* 1,set是一个固有的表,似乎。所以改成setter.没有,是旧的代码在后面。
-
* 2,现在ON_index和on_newindex的一些地方,没考虑会递归触发。要多用raw.
-
*/
-
#include<lua.h>
-
#include<lualib.h>
-
#include<lauxlib.h>
-
#include"utils.h"
-
-
int on_call(lua_State *L){
-
-
}
-
/*stack: obj key*/
-
int on_index(lua_State *L){
-
int obj_type = lua_type(L, 1);
-
-
if(obj_type == LUA_TUSERDATA){
-
-
/*尝试直接从metatable上获取该属性*/
-
lua_getmetatable(L, -2); /*stack: obj key mt*/
-
stk_rawget(L, -1, -2); /*stack: obj key mt mt.key*/
-
if(!lua_isnil(L, -1)){
-
return 1;
-
}
-
-
/*直接从mt上获取属性失败,尝试从get表里拿getter*/
-
else lua_pop(L, 1); /* stack: obj key mt */
-
lua_getfield(L, -1, "getter"); /*stack: obj key mt get */
-
stk_rawget(L, -1, 2); /*stack: obj key mt get get.key */
-
/*如果是getter, 直接调用*/
-
if(lua_isfunction(L, -1)){
-
lua_pushvalue(L, 1);
-
lua_pushvalue(L, 2);
-
lua_call(L, 2, 1);
-
return 1;
-
}
-
else{
-
printf("not a getter\n");
-
return 1;
-
}
-
}
-
}
-
-
/*stack: obj key vlaue*/
-
int on_newindex(lua_State *L){
-
const char *key = lua_tostring(L,2);
-
int value = lua_tointeger(L, 3);
-
printf("key:%s,value:%d\n", key, value);
-
lua_getmetatable(L, 1); /*stack: obj key value mt */
-
-
/*先看有没有对应的setter*/ /*BUG:尽量用rawget*/
-
lua_getfield(L, -1, "setter"); /*stack: obj key value mt set*/
-
lua_pushvalue(L, 2); /*stack: obj key value mt set key */
-
lua_rawget(L, -2); /*stack: obj key value mt set set.key*/ if(lua_isfunction(L, -1)){
-
lua_pushvalue(L, 1);
-
lua_pushvalue(L, 3);
-
lua_call(L, 2, 0);
-
return 0;
-
}
-
-
/*找不到对应的setter,直接把这个key挂到metatable里 */
-
else lua_pop(L, 2);
-
lua_pushvalue(L, 2);
-
lua_pushvalue(L, 3);
-
lua_rawset(L, -3);
-
return 0;
-
-
lua_pushvalue(L, -3); /*stack: obj key value mt key */
-
lua_pushvalue(L, -3); /*stack: obj key value mt key value*/
-
lua_rawset(L, -3); /*stack: obj key value mt */
-
-
lua_settop(L, 3);
-
return 0;
-
}
utils.c
-
#include<lua.h>
-
#include<lualib.h>
-
#include<lauxlib.h>
-
#include "utils.h"
-
-
void stk_rawget(lua_State
-
-
*L, int tbl_index, int key_index){
-
lua_pushvalue(L, key_index);
-
if(tbl_index < 0)
-
-
tbl_index--;
-
lua_rawget(L, tbl_index);
-
}
dog.c
-
#include"dog.h"
-
#include<lauxlib.h>
-
#include<lualib.h>
-
#include<stdlib.h>
-
int _dog_say(struct Dog *dog, char *msg){
-
printf("voice from dog: %s\n", msg);
-
return 123;
-
}
-
-
struct Dog * dog_new(int age){
-
struct Dog* d= malloc(sizeof(struct Dog));
-
d->age = age;
-
return d;
-
}
dog.h
-
#include<lauxlib.h>
-
#include<lualib.h>
-
struct Dog{
-
int age;
-
};
-
typedef struct Dog Dog;
-
int _dog_say(struct Dog *, char * msg);
-
struct Dog * dog_new(int age)
wrapper.c
-
/*
-
* 1,lua_call一个函数,会为它开启一个新stack,由母栈向子栈复制参数,
-
* 由子栈向母栈复制返回值。it ought be as this.
-
*/
-
#include<stdio.h>
-
#include<lua.h>
-
#include<lualib.h>
-
#include"dog.h"
-
#include "mklua_event.h"
-
#include"mklua.h"
-
int first_time = 1;
-
-
/*stack age */
-
int dog_new000(lua_State *L){
-
int age = lua_tointeger(L, 1);
-
struct Dog * dog = dog_new(100);
-
mklua_pushusertype(L, dog, "Dog");
-
return 1;
-
}
-
-
/*stack: obj value*/
-
int dog_set_age(lua_State *L){
-
struct Dog *d = lua_touserdata(L, 1);
-
-
d->age = lua_tointeger(L, 2);
-
return 0;
-
}
-
-
/*1, auto generated by karma
-
*3, >>> | table | key |
-
*/
-
int dog_get_age(lua_State *L){
-
struct Dog *d = lua_touserdata(L, -2);
-
printf("dog addr:%x,d->age:%d\n", d,d->age);
-
lua_pushinteger(L, d->age);
-
return 1;
-
}
-
-
-
-
int mklua_open_Dog(lua_State *L){
-
int ebp = lua_gettop(L);
-
begin_class_tbl(L, "Dog");
-
mklua_member(L, "age", dog_get_age, dog_set_age);
-
mklua_function(L, "new", dog_new000);
-
end_class_tbl(L);
-
lua_settop(L, ebp);
-
-
luaL_getmetatable(L, "Dog");
-
return 1;
-
}
-
-
-
/*prototype: userdata create(char * class_name)*/
-
int create(lua_State *L){
-
if(first_time){
-
first_time = 0;
-
mklua_open_Dog(L);
-
}
-
if(!lua_isstring(L, -1)) {
-
printf("not a valid string\n");
-
return 1;
-
}
-
const char *class_name = lua_tostring(L, -1);
-
struct Dog *dog = lua_newuserdata(L, sizeof(struct Dog));
-
luaL_getmetatable(L, class_name);
-
if(lua_isnil(L, -1)){
-
printf("can not find class:%s\n", class_name);
-
return 1;
-
}
-
else lua_setmetatable(L, -2);
-
dog->age = 10;
-
return 1;
-
}
-
-
int luaopen_dog(lua_State *L){
-
lua_register(L, "opendog", mklua_open_Dog);
-
return 0;
-
}
阅读(1807) | 评论(0) | 转发(0) |