Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7278594
  • 博文数量: 512
  • 博客积分: 12019
  • 博客等级: 上将
  • 技术积分: 6857
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-01 16:46
文章分类

全部博文(512)

文章存档

2024年(2)

2022年(2)

2021年(6)

2020年(59)

2019年(4)

2018年(10)

2017年(5)

2016年(2)

2015年(4)

2014年(4)

2013年(16)

2012年(47)

2011年(65)

2010年(46)

2009年(34)

2008年(52)

2007年(52)

2006年(80)

2005年(22)

分类: C/C++

2011-01-10 12:57:06

若想在lua内使用c++类函数接口可参考如下:


#include <stdio.h>
#include<iostream>
//g++ -g lua_api-new.cpp -I/usr/local/include /usr/local/lib/liblua.a

using namespace std;
extern "C"
{
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
}
#define TRACE_TOP printf("top=%d\n",lua_gettop(L));

template <class T> class LuaMgr
{
    public:
        static void Register(lua_State *L)
        {
            //构造函数 放到全局中(实际中建议集中放到单独表内)

            lua_pushcfunction(L, &LuaMgr <T>::constructor);
            lua_setglobal(L, T::classname);
            
            //建立元表

            luaL_newmetatable(L, T::classname);
            //设置垃圾回收

            lua_pushstring(L, "__gc");
            lua_pushcfunction(L, &LuaMgr <T>::gc_obj);
            lua_rawset(L, -3);
            
            //设置index

            lua_pushstring(L, "__index");
            lua_pushvalue(L, -2);
            lua_rawset(L, -3);
            
      //设置类成员函数。 注意此部分的语法:function并没有直接声明在模板内

            for (int i = 0; T::function[i].name; i++)
            {
             lua_pushstring(L, T::function[i].name);
             lua_pushnumber(L, i); //upvalue

             lua_pushcclosure(L, &LuaMgr<T>::thunk, 1);
             lua_rawset(L, -3);          //table["T::function[i].name"] = thunk;

            
            }
        
        }
    
        static int constructor(lua_State *L) //构造函数返回表,该函数用于脚本调用

        {
         T* obj = new T(L); //实际建立一个对象。可采用共享内存

         T** u = (T**)lua_newuserdata(L, sizeof(T*)); //获得一个指针

         *u = obj;
        
         //设置u元表

         luaL_getmetatable(L, T::classname);
         lua_setmetatable(L, -2);
      
       return 1; //返回u

         }
   
    //该函数用于c层调用,创建对象。由于没有直接返回lua,而没有被引用,要防止被释放

       static void* c_create(lua_State *L)
        {
         T* obj = new T(L); //实际建立一个对象。可采用共享内存

         void** u = (void**)lua_newuserdata(L, sizeof(T*)); //获得一个指针

         *u = obj;
        
         //设置u元表

         luaL_getmetatable(L, T::classname);
         lua_setmetatable(L, -2);
       lua_pop(L,1);
       //最好存放在表内,防止在被释放,如放到全局lua_setglobal(L,"aaafff");

       return u; //返回u

         }
      static int thunk(lua_State *L)
        {
            int i = (int)lua_tonumber(L, lua_upvalueindex(1));
            T** obj = static_cast <T**>(luaL_checkudata(L, 1, T::classname));
            return ((*obj)->*(T::function[i].mfunc))(L);
            
        }
    
        static int gc_obj(lua_State *L)
        {
            T** obj = static_cast <T**>(luaL_checkudata(L, -1, T::classname));
            delete (*obj);
            printf("deleteing\n");
            return 0;
        }
        
        struct RegType
        {
         const char *name;
         int(T::*mfunc)(lua_State*);
         };

        
};



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 = a+b;//add(a, b);

            lua_pushnumber(L, result);
            return 1;
        }
/******************只需增加 ****************************************/        
        friend class LuaMgr <Foo>;
        private:
            static const LuaMgr <Foo>::RegType function[];
     static const char classname[];
    
};

const char Foo::classname[] = "Foo";
const LuaMgr <Foo>::RegType Foo::function[] =
{
    { "foo", &Foo::foo},
    { "add_func", &Foo::n_add},
    { NULL , NULL}
};
/******************只需增加 end****************************************/



//驱动程序

int main()
{

    lua_State *L = lua_open();
    luaopen_base(L);
    
    LuaMgr <Foo>::Register(L);

    luaL_dofile(L, "t.lua");
    
    //直接在c 内建立userdata.可以把该user传给lua,在lua内操作对象。lua_newuserdata 地址和lua对象(TValue值)是不同的

    //创建时候,必须保存lua对象 ,直接压入地址不行 。可在lapi.h 内增加接口 TValue * luaA_getobject (lua_State *L,int indx ) {return index2adr(L, indx);}

    //void** u = (void** )LuaMgr ::c_create(L); //

    
    lua_close(L);
    return 0;
}



lua 代码

function f(ab)
    print(ab)

end

ret ,err= pcall(f, "hello world")
print( ret)
print(err)
print("okkkkkkkkkkk")


阅读(9094) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-03-07 08:34:24

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com