分享

lua 操作 C++ manipulate c++ class with lua

 quasiceo 2014-01-17

lua 操作 C++

manipulate c++ class with lua


lua 操作 C++的类 ;manipulate c++ class with lua

准备弄cocos2dx的lua,捣腾一下lua,留点印记给后面的童鞋参考。(俺也是半吊子,如果看官发现啥不妥的地方,请使劲喷。我全接受)


1、版本:这是个坑。

首先 pil (programming in lua)国人(似乎是风云大大)翻译的版本是5.0 有点低了。

cocos2dx 2.15用的是lua 5.1 ,

最新的lua 是5.2 ,

最新的pil 3rd 也是5.2;

5.0 ;5.1; 5.2的函数变化了不少,刚接触的时候会遇到即使是copy的代码也跑错的时候,就看你的code和lua环境是否一致吧。 网上大多代码示例都是5.0的,要稍加修改。


2、看书,lua不大,也不复杂。如果不是研究lua代码实现的话,入门还是比较快的。

先把pil仔细翻几遍,对语法都ok,然后再看 C 绑定的部分。这块主要是metatable __index __newindex的几个概念搞清晰。即可。


3、c,c++

这个其实就是用到上面(2)提到的技巧而已,本质上就是lua来通过glue代码间接操作C++的class而已。


废话不多说,赶着睡觉呢。。。。其实也说不清。看代码吧。加了详细的注释了。

makefile

all:
	g++ -g3 -o cheneeout chenee.cpp  -llua


clean:
	rm -R *dSYM *out


chenee.lua
print "test lua access C++ Class"

local a = Animal("dog")
--local a = Animal.creat("dog")
a:setAge(100)

a:sound()

print ("age is :" .. a:getAge())



chenee.cpp

//
//@chenee:this Demo showing how to manipulate the C++ class with LUA
// LUA = the moon
//
#include <stdio.h>
#include <string>
#include <iostream>


extern "C"{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}


//@chenee: to dump the lua stack
static void stackDump(lua_State * L)
{
	int		i;
	int		top = lua_gettop(L);	/* depth of the stack */
	for (i = 1; i <= top; i++) {	/* repeatforeachlevel */
		int		t = lua_type(L, i);
		switch (t) {
		case LUA_TSTRING:{ /* strings */
				printf("'%s'", lua_tostring(L, i));
				break;
			}
		case LUA_TBOOLEAN:{ /* booleans */
				printf(lua_toboolean(L, i) ? "true" : "false");
				break;
			}
		case LUA_TNUMBER:{ /* numbers */
				printf("%g", lua_tonumber(L, i));
				break;
			}
		default:{	/* other values */
				printf("%s", lua_typename(L, t));
				break;
			}
		}
		printf("  ");	/* put a separator */
	}
	printf("\n");		/* end the listing */
}



using namespace std;

//
//@chenee: the class to be deal with;
//
class Animal{
public:
    Animal(std::string name):age(0){ this->name = name;};
    void setAge(int age) { this->age = age;};
    int getAge(){ return this->age;};
    void sound(){ cout << " -- Animal name:   " << this->name << "  and it's Age:"<< this->age << endl;};
private:
    string name;
    int age;
};


//
//@chenee: this class used as a tool to expose interfaces to lua
//
class LuaAnimal{
    static const string className;
    static const luaL_reg methods[];
    static const luaL_reg methods_f[];

    static int creat(lua_State *L){
        string name (lua_tostring(L,1));
        Animal *a = new Animal(name);

        void **p = (void**)lua_newuserdata(L,sizeof(void*));
        *p = a;

      luaL_getmetatable(L, className.c_str());
      lua_setmetatable(L, -2);
      return 1;
    }
    static int gc_animal(lua_State *L) {
        Animal *a = (Animal*)(*(void**)lua_touserdata(L,1));
        delete a;
//        cout << "Gc ....." << endl;
        return 0;
    }
    static Animal* getAnimal(lua_State *L){
        luaL_checktype(L,1,LUA_TUSERDATA);
        void *ud = luaL_checkudata(L,1,className.c_str());
        if(!ud){
            luaL_typerror(L,1,className.c_str());
        }
        return *(Animal**)ud;
    }
    static int sound(lua_State *L){
        Animal *a = getAnimal(L);
        a->sound();
        return 1;
    }
    static int setAge(lua_State *L){
        Animal *a = getAnimal(L);
        double age = luaL_checknumber(L, 2);
        a->setAge(int(age));
        return 0;
    }
    static int getAge(lua_State *L){
        Animal *a = getAnimal(L);
        int age = a->getAge();
       lua_pushinteger(L, age);
        return 1;
    }
public:

    static void Register(lua_State* L) {
        //1: new methods talbe for L to save functions
        lua_newtable(L);
        int methodtable = lua_gettop(L);

        //2: new metatable for L to save "__index" "__newindex" "__gc" "__metatable" ...
        luaL_newmetatable(L, className.c_str());
        int metatable   = lua_gettop(L);

        //3: metatable["__metatable"] = methodtable
        lua_pushliteral(L, "__metatable");
        lua_pushvalue(L, methodtable);
        lua_settable(L, metatable);  // hide metatable from Lua getmetatable()

        //4: metatable["__index"] = methodtable
        lua_pushliteral(L, "__index");
        lua_pushvalue(L, methodtable);
        lua_settable(L, metatable);

        //5: metatable["__gc"] = gc_animal 
        lua_pushliteral(L, "__gc");
        lua_pushcfunction(L, gc_animal);
        lua_settable(L, metatable);

        lua_pop(L, 1);  // drop metatable

        //6: for objct:
        // name == 0 set object function to "methods"
        //eg:Animal a = Animal("xx");
        //a:func() in this "methods" table;
        luaL_openlib(L, 0, methods, 0);  // fill methodtable
        lua_pop(L, 1);  // drop methodtable

        //7.1: for Class:
        //name = "classname" , so this set Class function to "methods_f"
        //eg:Animal a = Animal:creat("xx");
        //Animal:creat() in this "methods_f" tables;
//        luaL_openlib(L, className.c_str(), methods_f, 0);

        //7.2: for Class:
        //add global function "Classname", so we Animal() is a global function now
        //Animal a = Animal("xx");
        //function Animal()in lua will call "creat" in C++
        lua_register(L, className.c_str(), creat);
    }

};

const string 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[] = {
    {"creat", LuaAnimal::creat},
    {NULL, NULL}
};

int main()
{
	lua_State      *L = luaL_newstate();
    luaL_openlibs(L);
//
    LuaAnimal::Register(L);

	if (luaL_loadfile(L, "chenee.lua") || lua_pcall(L, 0, 0, 0)){
        cout << "cannot run config. file:" << lua_tostring(L,-1) << endl;
    }

  lua_close(L);
  return 0;

}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章