C++11改写的lua绑定库,1900行

//

//  LuaScript.h

//  Common

//

//  Created by Azure on 14-8-13.

//  Copyright (c) 2014年 Azure. All rights reserved.

//

 

#ifndef Common_LuaScript_h

#define Common_LuaScript_h

 

#include "../BaseCode.h"

 

#include <cstdint>

#include <cstdarg>

#include <cstdlib>

#include <string>

#include <iostream>

#include <sstream>

#include <vector>

#include <list>

#include <set>

#include <map>

#include <string>

#include <exception>

 

extern "C"

{

#include "lua.h"

#include "lualib.h"

#include "lauxlib.h"

};

 

//////////////////////////////////////////////////////

//传string到lua只会传指针,所以不能传临时变量过去

//////////////////////////////////////////////////////

 

namespace Lynx {

    //不想里面的暴露在外,我们只用luascript,和TRegister

    namespace detail {

 

        //////////////////////////////////////////////////////

        //type

        //////////////////////////////////////////////////////

        static const char* INHERIT_TABLE = "inherit_table";

        struct CppVoid{};

        

        struct LuaStringTool

        {

            inline static const char* c_str(const std::string& s) { return s.c_str(); }

            inline static const char* c_str(const char* s) { return s; }

        };

        

        class LuaException : public std::exception

        {

            std::string _err;

        public:

            explicit LuaException(const char* err):_err(err) {}

            explicit LuaException(const std::string& err):_err(err) {}

            explicit LuaException(std::string&& err):_err(err) {}

            

            ~LuaException() noexcept {}

            

            const char* what() const noexcept { return _err.c_str(); }

        };

        

        class LuaTool

        {

        public:

            static void dumpStack(lua_State* ls)

            {

                int i;

                int top = lua_gettop(ls);

                

                for(i = 1; i <= top; ++i ){

                    int t = lua_type(ls,i);

                    switch (t) {

                        case LUA_TSTRING:

                            std::cout << lua_tostring(ls, i);

                            break;

                        case LUA_TBOOLEAN:

                            std::cout << (lua_toboolean(ls, i) ? "true" : "false");

                            break;

                        case LUA_TNUMBER:

                            std::cout << lua_tonumber(ls, i);

                            break;

                        case LUA_TTABLE:

                            std::cout << "table begin \n";

                            lua_pushnil(ls);

                            while(lua_next(ls,i) != 0){

                                std::cout << lua_typename(ls,lua_type(ls,-2)) << " - "

                                << lua_typename(ls, lua_type(ls,-1)) << '\n';

                                

                                lua_pop(ls, 1);

                            }

                            std::cout << "table end";

                            break;

                        default:

                            std::cout << lua_typename(ls, t);

                            break;

                    }

                    std::cout << " ";

                }

                std::cout << '\n';

            }

 

            static std::string dumpError(lua_State* ls)

            {

                std::string ret(" tracback:");

                ret.append(lua_tostring(ls, -1));

                return ret;

            }

        };

 

        typedef int (*LuaFunction_t)(lua_State*);

        

        class LuaNil {};

        

        template< typename T >

        struct TUserDataForObject

        {

            TUserDataForObject(T* p = nullptr) : _obj(p) {}

            T* _obj;

        };

        

        template< typename T >

        struct TLuaTypeInfo

        {

            static std::string _name;

            static std::string _inheritName;

            static void setName( const std::string& name,const std::string& inheritName = "" )

            {

                _name = name;

                _inheritName = inheritName;

            }

            

            inline static const char* getName() { return _name.c_str(); }

            inline static const char* getInheritName() { return _inheritName.c_str(); }

            inline static bool isRegisted() { return !_name.empty(); }

            inline static bool isInherit() { return !_inheritName.empty(); }

        };

        template< typename T >

        std::string TLuaTypeInfo<T>::_name;

        template< typename T >

        std::string TLuaTypeInfo<T>::_inheritName;

        

        template< typename ArgType >

        struct TReferenceTraits;

        

        template< typename ArgType >

        struct TReferenceTraits

        {

            typedef ArgType ArgType_t;

        };

        

        template<>

        struct TReferenceTraits<const std::string&>

        {

            typedef std::string ArgType_t;

        };

        

        template<>

        struct TReferenceTraits<std::string&>

        {

            typedef std::string ArgType_t;

        };

        

        template< typename T >

        struct TReferenceTraits<const T*>

        {

            typedef T* ArgType_t;

        };

        

        template< typename T >

        struct TReferenceTraits<const T&>

        {

            typedef T ArgType_t;

        };

        

        template<>

        struct TReferenceTraits<const char*>

        {

            typedef char* ArgType_t;

        };

        

        template< typename T >

        struct TInitValueTrait;

        

        template< typename T >

        struct TInitValueTrait

        {

            inline static T value() { return T(); }

        };

        

        template< typename T >

        struct TInitValueTrait<const T*>

        {

            inline static T* value() { return nullptr; }

        };

        

        template< typename T >

        struct TInitValueTrait<const T&>

        {

            inline static T value() { return T(); }

        };

        

        template<>

        struct TInitValueTrait<std::string>

        {

            inline static const char* value() { return ""; }

        };

        

        template<>

        struct TInitValueTrait<const std::string&>

        {

            inline static const char* value() { return ""; }

        };

        

        template< typename T >

        struct TLuaOp;

        

        template<>

        struct TLuaOp<const char*>

        {

            static void pushStack(lua_State* ls,const char* arg)

            {

                lua_pushstring(ls,arg);

            }

            static int luaToValue(lua_State* ls,int pos,std::string& param)

            {

                param = luaL_checkstring(ls,pos);

                return 0;

            }

        };

        

        template<>

        struct TLuaOp<LuaNil>

        {

            static void pushStack(lua_State* ls,const LuaNil& arg)

            {

                lua_pushnil(ls);

            }

        };

        

        template<>

        struct TLuaOp<CppVoid>

        {

            static int getRetValue(lua_State* ls,int pos,CppVoid& param)

            {

                return 0;

            }

        };

        

        template<>

        struct TLuaOp<int64_t>

        {

            static void pushStack(lua_State* ls,int64_t arg)

            {

                std::stringstream ss;

                ss<<arg;

                std::string str = ss.str();

                lua_pushlstring(ls,str.c_str(),str.length());

            }

            

            static int getRetValue(lua_State* ls,int pos,int64_t& param)

            {

                if(!lua_isstring(ls,pos))

                    return -1;

                

                size_t len = 0;

                const char* src = lua_tolstring(ls,pos,&len);

                param = (int64_t)strtoll(src,nullptr,10);

                return 0;

            }

            

            static int luaToValue(lua_State* ls,int pos,int64_t& param)

            {

                size_t len = 0;

                const char* str = luaL_checklstring(ls,pos,&len);

                param = (int64_t)strtoll(str,nullptr,10);

                return 0;

            }

        };

 

        template<>

        struct TLuaOp<uint64_t>

        {

            static void pushStack(lua_State* ls,uint64_t arg)

            {

                std::stringstream ss;

                ss<<arg;

                std::string str = ss.str();

                lua_pushlstring(ls,str.c_str(),str.length());

            }

            

            static int getRetValue(lua_State* ls,int pos,uint64_t& param)

            {

                if(!lua_isstring(ls,pos))

                    return -1;

                

                size_t len = 0;

                const char* src = lua_tolstring(ls,pos,&len);

                param = (int64_t)strtoull(src,nullptr,10);

                return 0;

            }

            

            static int luaToValue(lua_State* ls,int pos,uint64_t& param)

            {

                size_t len = 0;

                const char* str = luaL_checklstring(ls,pos,&len);

                param = (int64_t)strtoull(str,nullptr,10);

                return 0;

            }

        };

 

        template<> struct TLuaOp<char>

        {

            static void pushStack(lua_State* ls,char arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,char& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                

                param = (char)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,char& param)

            {

                param = (char)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<unsigned char>

        {

            static void pushStack(lua_State* ls,unsigned char arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,unsigned char& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                

                param = (unsigned char)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,unsigned char& param)

            {

                param = (unsigned char)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<short>

        {

            static void pushStack(lua_State* ls,short arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,short& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                

                param = (short)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,short& param)

            {

                param = (short)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<unsigned short>

        {

            static void pushStack(lua_State* ls,unsigned short arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,unsigned short& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                

                param = (unsigned short)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,unsigned short& param)

            {

                param = (unsigned short)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<int>

        {

            static void pushStack(lua_State* ls,int arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,int& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                

                param = (int)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,int& param)

            {

                param = (int)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<unsigned int>

        {

            static void pushStack(lua_State* ls,unsigned int arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,unsigned int& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                

                param = (unsigned int)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,unsigned int& param)

            {

                param = (unsigned int)luaL_checknumber(ls,pos);

                return 0;

            }

        };

 

        template<> struct TLuaOp<bool>

        {

            static void pushStack(lua_State* ls,bool arg)

            {

                lua_pushboolean(ls,arg);

            }

            

            static int getRetValue(lua_State* ls,int pos,bool& param)

            {

                //nil auto transfer to false

                if( lua_isnil(ls,pos)){

                    param = false;

                    return 0;

                }

                if(!lua_isboolean(ls,pos)){

                    return -1;

                }

                param = bool(lua_toboolean(ls,pos));

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,bool& param)

            {

                luaL_checktype(ls,pos,LUA_TBOOLEAN);

                param = (bool)lua_toboolean(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<std::string>

        {

            static void pushStack(lua_State* ls,const std::string& arg)

            {

                lua_pushlstring(ls,arg.c_str(),arg.length());

            }

            

            static int getRetValue(lua_State* ls,int pos,std::string& param)

            {

                if(!lua_isstring(ls,pos))

                    return -1;

                

                lua_pushvalue(ls,pos);

                size_t len = 0;

                const char* src = lua_tolstring(ls,-1,&len);

                param.assign(src,len);

                lua_pop(ls,1);

                

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,std::string& param)

            {

                size_t len = 0;

                const char* str = luaL_checklstring(ls,pos,&len);

                param.assign(str,len);

                return 0;

            }

        };

 

        template<>

        struct TLuaOp<const std::string&>

        {

            static void pushStack(lua_State* ls,const std::string& arg)

            {

                lua_pushlstring(ls,arg.c_str(),arg.length());

            }

            

            static int getRetValue(lua_State* ls,int pos,std::string& param)

            {

                if(!lua_isstring(ls,pos))

                    return -1;

                

                lua_pushvalue(ls,pos);

                size_t len = 0;

                const char* src = lua_tolstring(ls,-1,&len);

                param.assign(src,len);

                lua_pop(ls,1);

                

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,std::string& param)

            {

                size_t len = 0;

                const char* str = luaL_checklstring(ls,pos,&len);

                param.assign(str,len);

                return 0;

            }

        };

 

        template<> struct TLuaOp<float>

        {

            static void pushStack(lua_State* ls,float arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,float& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                

                param = (float)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,float& param)

            {

                param = (float)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<double>

        {

            static void pushStack(lua_State* ls,double arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,double& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                param = (double)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,double& param)

            {

                param = (double)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<long>

        {

            static void pushStack(lua_State* ls,long arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,long& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                param = (long)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,long& param)

            {

                param = (long)luaL_checknumber(ls,pos);

                return 0;

            }

        };

        

        template<> struct TLuaOp<unsigned long>

        {

            static void pushStack(lua_State* ls,unsigned long arg)

            {

                lua_pushnumber(ls,(lua_Number)arg);

            }

            static int getRetValue(lua_State* ls,int pos,unsigned long& param)

            {

                if(!lua_isnumber(ls,pos))

                    return -1;

                param = (unsigned long)lua_tonumber(ls,pos);

                return 0;

            }

            static int luaToValue(lua_State* ls,int pos,unsigned long& param)

            {

                param = (unsigned long)luaL_checknumber(ls,pos);

                return 0;

            }

        };

 

        template<>

        struct TLuaOp<void*>

        {

            static void pushStack(lua_State* ls,void* arg)

            {

                lua_pushlightuserdata(ls,arg);

            }

            static int getRetValue(lua_State* ls,int pos,void*& param)

            {

                if(!lua_isuserdata(ls,pos))

                {

                    LUA_ERROR(format("userdata param expected,but type<%s>",lua_typename(ls,lua_type(ls,pos))));

                    return -1;

                }

                param = lua_touserdata(ls,pos);

                return 0;

            }

            

            static int luaToValue(lua_State* ls,int pos,void*& param)

            {

                if(!lua_isuserdata(ls,pos)){

                    luaL_argerror(ls,1,"userdata param expected");

                    return -1;

                }

                param = lua_touserdata(ls,pos);

                return 0;

            }

        };

 

        template< typename T >

        struct TLuaOp<T*>

        {

            static void pushStack(lua_State* ls,T* arg)

            {

                void* ptr = lua_newuserdata(ls,sizeof(TUserDataForObject<T>));

                new (ptr) TUserDataForObject<T>(arg);

                

                luaL_getmetatable(ls,TLuaTypeInfo<T>::getName());

                lua_setmetatable(ls,-2);

            }

            static int getRetValue(lua_State* ls,int pos,T*& param)

            {

                if(false == TLuaTypeInfo<T>::isRegisted()){

                    luaL_argerror(ls,pos,"type not supported");

                }

                

                void *argData = lua_touserdata(ls,pos);

                

                if(NULL == argData){

                    LUA_ERROR(format("expect<%s> but <%s> NULL",TLuaTypeInfo<T>::getName(),

                             lua_typename(ls,lua_type(ls,pos))));

                    return -1;

                }

                

                if(0 == lua_getmetatable(ls,pos)){

                    return -1;

                }

                

                luaL_getmetatable(ls,TLuaTypeInfo<T>::getName());

                if(0 == lua_rawequal(ls,-1,-2)){

                    lua_getfield(ls,-2,INHERIT_TABLE);

                    if(0 == lua_rawequal(ls,-1,-2)){

                        LUA_ERROR(format("expect<%s> but <%s> not equal",TLuaTypeInfo<T>::getName(),

                                 lua_typename(ls,lua_type(ls,pos))));

                        lua_pop(ls,3);

                        return -1;

                    }

                    lua_pop(ls,3);

                }else{

                    lua_pop(ls,2);

                }

                T* retPtr = ((TUserDataForObject<T>*)argData)->_obj;

                if( NULL == retPtr){

                    return -1;

                }

                

                param = retPtr;

                return 0;

            }

            

            static int luaToValue(lua_State* ls,int pos,T*& param)

            {

                if(false == TLuaTypeInfo<T>::isRegisted()){

                    luaL_argerror(ls,pos,"type not supported");

                }

                void *argData = lua_touserdata(ls,pos);

                if(NULL == argData || 0 == lua_getmetatable(ls,pos)){

                    std::string buf;

                    buf.reserve(128);

                    buf.append("\'").append(TLuaTypeInfo<T>::getName()).append("\' arg1 connot be null");

                    luaL_argerror(ls,pos,buf.c_str());

                }

                

                luaL_getmetatable(ls,TLuaTypeInfo<T>::getName());

                if(0 == lua_rawequal(ls,-1,-2)){

                    lua_getfield(ls,-2,INHERIT_TABLE);

                    if(0 == lua_rawequal(ls,-1,-2)){

                        lua_pop(ls,3);

                        std::string buf;

                        buf.reserve(128);

                        buf.append("\'").append(TLuaTypeInfo<T>::getName()).append("\' arg1 type not equal");

                        luaL_argerror(ls,pos,buf.c_str());

                    }

                    lua_pop(ls,3);

                }else{

                    lua_pop(ls,2);

                }

                

                T* retPtr = ((TUserDataForObject<T>*)argData)->_obj;

                if(NULL == retPtr){

                    std::string buf;

                    buf.reserve(128);

                    buf.append("\'").append(TLuaTypeInfo<T>::getName()).append("\' object ptr cannot be null");

                    luaL_argerror(ls,pos,buf.c_str());

                }

                

                param = retPtr;

                return 0;

            }

        };

 

        template< typename T >

        struct TLuaOp<const T*>

        {

            static void pushStack(lua_State* ls,const T* arg)

            {

                TLuaOp<T*>::pushStack(ls,const_cast<T*>(arg));

            }

            

            static int getRetValue(lua_State* ls,int pos,T*& param)

            {

                return TLuaOp<const T*>::getRetValue(ls,pos,param);

            }

            

            static int luaToValue(lua_State* ls,int pos,T*& param)

            {

                return TLuaOp<const T*>::luaToValue(ls,pos,param);

            }

        };

        

        template< typename T >

        struct TLuaOp< std::vector<T> >

        {

            static void pushStack(lua_State* ls,const std::vector<T>& arg)

            {

                lua_newtable(ls);

                int i = 1;

                for(auto x : arg ){

                    TLuaOp<int>::pushStack(ls,i);

                    TLuaOp<T>::pushStack(ls,x);

                    lua_settable(ls,-3);

                    ++i;

                }

            }

            

            static int getRetValue(lua_State* ls,int pos,std::vector<T>& param)

            {

                if(0 == lua_istable(ls,pos))

                    return -1;

                

                lua_pushnil(ls);

                int realPos = pos;

                if(pos < 0 )

                    realPos = realPos - 1;

                

                while( lua_next(ls,realPos) != 0){

                    param.push_back(T());

                    if(TLuaOp<T>::getRetValue(ls,-1,param[param.size()-1]) < 0)

                        return -1;

                    lua_pop(ls,1);

                }

                return 0;

            }

 

            static int luaToValue(lua_State* ls,int pos,std::vector<T>& param)

            {

                luaL_checktype(ls,pos,LUA_TTABLE);

                

                lua_pushnil(ls);

                int realPos = pos;

                if(pos < 0)

                    realPos = realPos - 1;

                while (lua_next(ls,realPos) != 0) {

                    param.push_back(T());

                    if(TLuaOp<T>::luaToValue(ls,-1,param[param.size()-1]) < 0)

                        luaL_argerror(ls,pos > 0 ? pos:-pos,"convert to vector failed");

        

                    lua_pop(ls,1);

                }

                return 0;

            }

        };

        

        template< typename T >

        struct TLuaOp< std::list<T> >

        {

            static void pushStack(lua_State* ls,const std::list<T>& arg)

            {

                lua_newtable(ls);

                int i = 1;

                for(auto x : arg ){

                    TLuaOp<int>::pushStack(ls,i);

                    TLuaOp<T>::pushStack(ls,x);

                    lua_settable(ls,-3);

                    ++i;

                }

            }

            

            static int getRetValue(lua_State* ls,int pos,std::list<T>& param)

            {

                if(0 == lua_istable(ls,pos))

                    return -1;

                lua_pushnil(ls);

                int realPos = pos;

                if(pos < 0)

                    realPos = realPos - 1;

                

                while (lua_next(ls,realPos) != 0) {

                    param.push_back(T());

                    if(TLuaOp<T>::getRetValue(ls,-1,(param.back())) < 0)

                        return -1;

                    lua_pop(ls,1);

                }

                return 0;

            }

 

            static int luaToValue(lua_State* ls,int pos,std::list<T>& param)

            {

                luaL_checktype(ls,pos,LUA_TTABLE);

                

                lua_pushnil(ls);

                int realPos = pos;

                if( pos < 0 )

                    realPos = realPos - 1;

                while (lua_next(ls,realPos) != 0 ) {

                    param.push_back(T());

                    if(TLuaOp<T>::luaToValue(ls,-1,(param.back())) < 0)

                        luaL_argerror(ls,pos > 0 ? pos : -pos ,"convert to list failed");

                    lua_pop(ls,1);

                }

                return 0;

            }

        };

        

        template< typename T >

        struct TLuaOp< std::set<T> >

        {

            static void pushStack(lua_State* ls,const std::set<T>& arg)

            {

                lua_newtable(ls);

                int i = 1;

                for( auto x : arg ){

                    TLuaOp<int>::pushStack(ls,i);

                    TLuaOp<T>::pushStack(ls,x);

                    lua_settable(ls,-3);

                    ++i;

                }

            }

            

            static int getRetValue(lua_State* ls,int pos,std::set<T>& param)

            {

                if(0 == lua_istable(ls,pos))

                    return -1;

                

                lua_pushnil(ls);

                int realPos = pos;

                if(pos < 0 )

                    realPos = realPos - 1;

                

                while (lua_next(ls,realPos) != 0) {

                    T val = TInitValueTrait<T>::value();

                    if( TLuaOp<T>::getRetValue(ls,-1,val) < 0 )

                        return -1;

                    param.insert(val);

                    lua_pop(ls,1);

                }

                return 0;

            }

        

            static int luaToValue(lua_State* ls,int pos,std::set<T>& param)

            {

                luaL_checktype(ls,pos,LUA_TTABLE);

                

                lua_pushnil(ls);

                int realPos = pos;

                if( pos < 0 )

                    realPos = realPos - 1;

                while( (lua_next(ls,realPos) != 0) ){

                    T val = TInitValueTrait<T>::value();

                    if( TLuaOp<T>::luaToValue(ls,-1,val) < 0 )

                        luaL_argerror(ls,pos > 0 ? pos : -pos,"convert to set failed");

                    

                    param.insert(val);

                    lua_pop(ls,1);

                }

                return 0;

            }

        };

        

        template< typename K, typename V >

        struct TLuaOp< std::map<K,V> >

        {

            static void pushStack(lua_State* ls,const std::map<K,V>& arg)

            {

                lua_newtable(ls);

                for( auto x : arg ){

                    TLuaOp<K>::pushStack(ls,x.first);

                    TLuaOp<V>::pushStack(ls,x.second);

                    lua_settable(ls,-3);

                }

            }

 

            static int getRetValue(lua_State* ls,int pos,std::map<K,V>& param)

            {

                if( 0 == lua_istable(ls,pos) )

                    return -1;

                

                lua_pushnil(ls);

                int realPos = pos;

                if( pos < 0 )

                    realPos = realPos - 1;

                

                while( lua_next(ls, realPos) != 0 ){

                    K key = TInitValueTrait<K>::value();

                    V val = TInitValueTrait<V>::value();

                    

                    if( TLuaOp<K>::getRetValue(ls,-2,key) < 0 ||

                       TLuaOp<V>::getRetValue(ls,-1,val) < 0)

                        return -1;

                    

                    param.insert(std::make_pair(key,val));

                    lua_pop(ls,1);

                }

                return 0;

            }

 

            static int luaToValue( lua_State* ls,int pos,std::map<K,V>& param)

            {

                luaL_checktype(ls,pos,LUA_TTABLE);

                

                lua_pushnil(ls);

                int realPos = pos;

                if( pos < 0 )

                    realPos = realPos - 1;

                while( (lua_next(ls,realPos) != 0 )){

                    K key = TInitValueTrait<K>::value();

                    V val = TInitValueTrait<V>::value();

                    if( TLuaOp<K>::getRetValue(ls,-2,key) < 0 ||

                       TLuaOp<V>::getRetValue(ls,-1,val) )

                        luaL_argerror(ls,pos > 0 ? pos : -pos ,"convert to map failed");

                    

                    param.insert(std::make_pair(key,val));

                    lua_pop(ls,1);

                }

                return 0;

            }

        };

        

        typedef int (*MetatableIndexFunc_t)(lua_State*,void*,const char*);

        typedef int (*MetatableNewIndexFunc_t)(lua_State*,void*,const char*,int);

#define LUA_ARG_POS(x)  (x)

#define TO_METATABLE_NAME(x)   detail::TOpTool::toMetatableName((x)).c_str()

        

        struct TOpTool

        {

            static std::string toMetatableName(const std::string& name)

            {

                return std::string("Lynx.") + name;

            }

        };

 

        template< typename T >

        struct TClassPropertyInfo

        {

            T _propertyPos;

            TClassPropertyInfo():_propertyPos(NULL){}

        };

 

        //记录类中字段的指针

        struct RealClassPropertyProcessor

        {

            MetatableIndexFunc_t      _indexImplFunc;

            MetatableNewIndexFunc_t   _newIndexImplFunc;

            void*                   _propertyPos;

            RealClassPropertyProcessor():_indexImplFunc(NULL),_newIndexImplFunc(NULL),_propertyPos(NULL) {}

        };

        

        template< typename FuncType >

        struct TUserDataForFunction

        {

            FuncType       _realFunc;

            TUserDataForFunction(FuncType func):_realFunc(func) {}

        };

 

        template< typename PropertyType >

        struct TUserDataForClassProperty : public RealClassPropertyProcessor

        {

            typedef TClassPropertyInfo<PropertyType>   RealClassPropertyInfo_t;

            RealClassPropertyInfo_t                       _propertyInfo;

        };

        

        //生成构造函数new,delete,index的实现类

        template< typename ClassType >

        struct TMetatableRegisterImpl

        {

            static int mtIndexFunction(lua_State* ls)

            {

                const char* key = luaL_checkstring(ls,LUA_ARG_POS(2));

                

                luaL_getmetatable(ls,TLuaTypeInfo<ClassType>::getName());

                int mtIndex = lua_gettop(ls);

                

                lua_getfield(ls,-1,key);

                lua_remove(ls,mtIndex);

                

                //没有这个字段,查找基类

                if( lua_isnil(ls,-1) && TLuaTypeInfo<ClassType>::isInherit()){

                    lua_pop(ls,1);

                    luaL_getmetatable(ls,TLuaTypeInfo<ClassType>::getInheritName());

                    mtIndex = lua_gettop(ls);

                    lua_getfield(ls,-1,key);

                    lua_remove(ls,mtIndex);

                }

                

                if( lua_isuserdata(ls,-1)){ //获取属性

                    RealClassPropertyProcessor* p = (RealClassPropertyProcessor*)lua_touserdata(ls,-1);

                    lua_pop(ls,1);

                    return (*(p->_indexImplFunc))(ls,p->_propertyPos,key);

                }else{

                    return 1;

                }

            }

 

            static int mtNewIndexFunction(lua_State* ls)

            {

                const char* key = luaL_checkstring(ls,LUA_ARG_POS(2));

                

                luaL_getmetatable(ls,TLuaTypeInfo<ClassType>::getName());

                int mtIndex = lua_gettop(ls);

                

                lua_getfield(ls,-1,key);

                lua_remove(ls,mtIndex);

                

                //没有这个字段,查找基类

                if(lua_isnil(ls,-1) && TLuaTypeInfo<ClassType>::isInherit()){

                    lua_pop(ls,1);

                    luaL_getmetatable(ls,TLuaTypeInfo<ClassType>::getInheritName());

                    mtIndex = lua_gettop(ls);

                    lua_getfield(ls,-1,key);

                    lua_remove(ls,mtIndex);

                }

                if(lua_isuserdata(ls,-1)){

                    RealClassPropertyProcessor* p = (RealClassPropertyProcessor*)lua_touserdata(ls,-1);

                    lua_pop(ls,1);

                    return (*(p->_newIndexImplFunc))(ls,p->_propertyPos,key,LUA_ARG_POS(3));

                }else{

                    return 1;

                }

            }

            

            static ClassType** userDataToObjectPtrAddress(lua_State* ls)

            {

                if( false == TLuaTypeInfo<ClassType>::isRegisted()){

                    luaL_argerror(ls,1,"arg 1 can not convert to class*,because the class has not registed to lua");

                }

                

                void* argData = luaL_checkudata(ls,1,TLuaTypeInfo<ClassType>::getName());

                if( NULL == argData ){

                    std::string buf;

                    buf.reserve(128);

                    buf.append("\'").append(TLuaTypeInfo<ClassType>::getName())

                    .append("\' expect arg 1 ,but arg == null");

                    luaL_argerror(ls,1,buf.c_str());

                }

                

                ClassType** retPtr = &(((TUserDataForObject<ClassType>*)argData)->_obj);

                return retPtr;

            }

            

            static ClassType* userDataToObject(lua_State* ls)

            {

                if( false == TLuaTypeInfo<ClassType>::isRegisted()){

                    luaL_argerror(ls,1,"arg 1 cannot convert to class*,because the class has not registed to lua");

                }

                void *argData = lua_touserdata(ls,1);

                if(NULL == argData){

                    luaL_argerror(ls,1,"arg 1 need userdata(cannot be null) param");

                }

                if( 0 == lua_getmetatable(ls,1)){

                    luaL_argerror(ls,1,"arg 1 has no metatable,it is not cpp type" );

                }

                

                luaL_getmetatable(ls,TLuaTypeInfo<ClassType>::getName());

                if( 0 == lua_rawequal(ls,-1,-2)){

                    //查找基类

                    lua_getfield(ls,-2,INHERIT_TABLE);

                    if( 0 == lua_rawequal(ls,-1,-2)){

                        lua_pop(ls,3);

                        luaL_argerror(ls,1,"type convert failed");

                    }

                    lua_pop(ls,3);

                }else{

                    lua_pop(ls,2);

                }

 

                ClassType* retPtr = ((TUserDataForObject<ClassType>*)argData)->_obj;

                if(NULL == retPtr){

                    std::string buf;

                    buf.reserve(128);

                    buf.append("\'").append(TLuaTypeInfo<ClassType>::getName()).append("\' object ptr cannot be null");

                    luaL_argerror(ls,1,buf.c_str());

                }

                return retPtr;

            }

            static int getPointer(lua_State* ls)

            {

                ClassType** objPtr = userDataToObjectPtrAddress(ls);

                int64_t addr = int64_t(*objPtr);

                TLuaOp<int64_t>::pushStack(ls,addr);

                return 1;

            }

        };

        

        template< typename ClassType,typename FuncType >

        struct TNewTraits;

        

        template< typename ClassType >

        struct TDeleteTraits

        {

            static int luaFunction(lua_State* ls)

            {

                ClassType** objPtr = TMetatableRegisterImpl<ClassType>::userDataToObjectPtrAddress(ls);

                

                delete *objPtr;

                *objPtr = nullptr;

                return 0;

            }

        };

     

        template< typename FuncType >

        struct TClassFunctionTraits;

        

        template< typename PropertyType,typename Ret >

        struct TClassPropertyTraits;

        

        template< typename FuncType >

        struct TFunctionTraits;

        

        //ClassType 为要注册的类型,CtorType为构造函数类型

        template< typename T >

        struct TLuaRegisterRouter;

        

        template< typename T >

        struct TLuaRegisterRouter

        {

            template< typename RegType >

            static void call(RegType* reg,T arg,const std::string& s)

            {

                reg->defClassProperty(arg,s);

            }

        };

 

        //////////////////////////////////////////////////////

        //TNewTraits

        //////////////////////////////////////////////////////

        template< typename ClassType >

        struct TNewTraits< ClassType,int() >

        {

            static int luaFunction(lua_State* ls)

            {

                return 0;

            }

        };

        

        //get the arg!

        template< typename T >

        typename TReferenceTraits<T>::ArgType_t getArg(lua_State* ls,int n)

        {

            typename TReferenceTraits<T>::ArgType_t arg = TInitValueTrait<T>::value();

            TLuaOp<typename TReferenceTraits<T>::ArgType_t>::luaToValue(ls,LUA_ARG_POS(n),arg);

            return arg;

        }

        

        template< typename ClassType >

        struct TNewTraits<ClassType,void()>

        {

            static int luaFunction(lua_State* ls)

            {

                void* userDataPtr = lua_newuserdata(ls,sizeof(TUserDataForObject<ClassType>));

                luaL_getmetatable(ls,TLuaTypeInfo<ClassType>::getName());

                lua_setmetatable(ls,-2);

                

                new(userDataPtr) TUserDataForObject<ClassType>(new ClassType());

                return 1;

            }

        };

        

        template< typename ClassType,typename... Args >

        struct TNewTraits<ClassType,void(Args...)>

        {

            static int luaFunction(lua_State* ls)

            {

                void* userDataPtr = lua_newuserdata(ls,sizeof(TUserDataForObject<ClassType>));

                luaL_getmetatable(ls,TLuaTypeInfo<ClassType>::getName());

                lua_setmetatable(ls,-2);

                

                int n = 2;

                new(userDataPtr) TUserDataForObject<ClassType>(new ClassType(getArg<Args>(ls,n++)...));

                return 1;

            }

        };

 

        //////////////////////////////////////////////////////

        //TClassFunctionTraits

        //////////////////////////////////////////////////////

        template< typename FuncClassType >

        struct TClassFunctionTraits<void(FuncClassType::*)()>

        {

            typedef void (FuncClassType::*DestFunc_t)();

            typedef TUserDataForFunction<DestFunc_t>        UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls,lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                (objPtr->*(registedData._realFunc))();

                return 0;

            }

        };

 

        template< typename FuncClassType,typename... Args >

        struct TClassFunctionTraits<void(FuncClassType::*)(Args...)>

        {

            typedef void (FuncClassType::*DestFunc_t)(Args...);

            typedef TUserDataForFunction<DestFunc_t>        UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls,lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                

                int n = 2;

                (objPtr->*(registedData._realFunc))(getArg<Args>(ls,n++)...);

                return 0;

            }

        };

 

        template< typename FuncClassType >

        struct TClassFunctionTraits<void(FuncClassType::*)()const>

        {

            typedef void (FuncClassType::*DestFunc_t)()const;

            typedef TUserDataForFunction<DestFunc_t>        UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls,lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                (objPtr->*(registedData._realFunc))();

                return 0;

            }

        };

        

        template< typename FuncClassType,typename... Args >

        struct TClassFunctionTraits<void(FuncClassType::*)(Args...)const>

        {

            typedef void (FuncClassType::*DestFunc_t)(Args...)const;

            typedef TUserDataForFunction<DestFunc_t>        UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls,lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                

                int n = 2;

                (objPtr->*(registedData._realFunc))(getArg<Args>(ls,n++)...);

                return 0;

            }

        };

 

        template< typename FuncClassType,typename Ret >

        struct TClassFunctionTraits<Ret(FuncClassType::*)()>

        {

            typedef Ret(FuncClassType::*DestFunc_t)();

            typedef TUserDataForFunction<DestFunc_t>            UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls, lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                Ret ret = (objPtr->*(registedData._realFunc))();

                TLuaOp<Ret>::pushStack(ls,ret);

                return 1;

            }

        };

 

        template< typename FuncClassType,typename Ret,typename... Args >

        struct TClassFunctionTraits<Ret(FuncClassType::*)(Args...)>

        {

            typedef Ret(FuncClassType::*DestFunc_t)(Args...);

            typedef TUserDataForFunction<DestFunc_t>            UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls, lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                

                int n = 2;

                Ret ret = (objPtr->*(registedData._realFunc))(getArg<Args>(ls,n++)...);

                TLuaOp<Ret>::pushStack(ls,ret);

                return 1;

            }

        };

 

        template< typename FuncClassType,typename Ret >

        struct TClassFunctionTraits<Ret(FuncClassType::*)()const>

        {

            typedef Ret(FuncClassType::*DestFunc_t)()const;

            typedef TUserDataForFunction<DestFunc_t>            UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls, lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                Ret ret = (objPtr->*(registedData._realFunc))();

                TLuaOp<Ret>::pushStack(ls,ret);

                return 1;

            }

        };

        

        template< typename FuncClassType,typename Ret,typename... Args >

        struct TClassFunctionTraits<Ret(FuncClassType::*)(Args...)const>

        {

            typedef Ret(FuncClassType::*DestFunc_t)(Args...)const;

            typedef TUserDataForFunction<DestFunc_t>            UserDataForFunctionInfo_t;

            

            static int luaFunction(lua_State* ls)

            {

                void* destData = lua_touserdata(ls, lua_upvalueindex(1));

                UserDataForFunctionInfo_t& registedData = *((UserDataForFunctionInfo_t*)destData);

                

                FuncClassType* objPtr = TMetatableRegisterImpl<FuncClassType>::userDataToObject(ls);

                

                int n = 2;

                Ret ret = (objPtr->*(registedData._realFunc))(getArg<Args>(ls,n++)...);

                TLuaOp<Ret>::pushStack(ls,ret);

                return 1;

            }

        };

 

        //////////////////////////////////////////////////////

        //TClassPropertyTraits

        //////////////////////////////////////////////////////

        template< typename ClassType,typename Ret >

        struct TClassPropertyTraits

        {

            typedef int (*ProcessIndexFunc_t)(lua_State*,void*,const char*);

            typedef int (*ProcessNewIndexFunc_t)(lua_State*,void*,const char*,int);

            

            typedef Ret Property_t;

            typedef Ret ClassType::* PropertyPtr_t;

            static int processIndex(lua_State* ls,void* fieldInfo,const char* key)

            {

                typedef TClassPropertyInfo<PropertyPtr_t>   ClassPropertyInfo_t;

                ClassType* objPtr = TMetatableRegisterImpl<ClassType>::userDataToObject(ls);

                

                ClassPropertyInfo_t *reg = (ClassPropertyInfo_t*)fieldInfo;

                PropertyPtr_t ptr = reg->_propertyPos;

                

                if(ptr){

                    TLuaOp<Property_t>::pushStack(ls,(objPtr->*ptr));

                    return 1;

                }else{

                    LUA_ERROR(format("none this field<%s>",key));

                    return 0;

                }

                

                return 0;

            }

            

            static int processNewIndex(lua_State* ls,void* fieldInfo,const char* key,int valueIndex)

            {

                typedef TClassPropertyInfo<PropertyPtr_t>   ClassPropertyInfo_t;

                ClassType* objPtr = TMetatableRegisterImpl<ClassType>::userDataToObject(ls);

                

                ClassPropertyInfo_t* reg = (ClassPropertyInfo_t*)fieldInfo;

                PropertyPtr_t ptr = reg->_propertyPos;

                

                if(ptr){

                    Property_t value = TInitValueTrait<Property_t>::value();

                    TLuaOp<Property_t>::luaToValue(ls,valueIndex,value);

                    (objPtr->*ptr) = value;

                    return 0;

                }else{

                    LUA_ERROR(format("none this field<%s>",key));

                    return 0;

                }

                

                return 0;

            }

        };

        

        //////////////////////////////////////////////////////

        //TFunctionTraits

        //////////////////////////////////////////////////////

        template<>

        struct TFunctionTraits<void(*)()>

        {

            typedef void(*DestFunc_t)();

            static int luaFunction(lua_State* ls)

            {

                void* userData = lua_touserdata(ls, lua_upvalueindex(1));

                

                DestFunc_t& registedFunc = *((DestFunc_t*)userData);

                registedFunc();

                return 0;

            }

        };

        

        template< typename... Args >

        struct TFunctionTraits<void(*)(Args...)>

        {

            typedef void(*DestFunc_t)(Args...);

            static int luaFunction(lua_State* ls)

            {

                void* userData = lua_touserdata(ls, lua_upvalueindex(1));

                DestFunc_t& registedFunc = *((DestFunc_t*)userData);

                

                int n = 1;

                registedFunc(getArg<Args>(ls,n++)...);

 

                return 0;

            }

        };

        

        template< typename Ret >

        struct TFunctionTraits<Ret(*)()>

        {

            typedef Ret(*DestFunc_t)();

            static int luaFunction(lua_State* ls)

            {

                void* userData = lua_touserdata(ls, lua_upvalueindex(1));

                DestFunc_t& registedFunc = *((DestFunc_t*)userData);

                

                Ret ret = registedFunc();

                TLuaOp<Ret>::pushStack(ls,ret);

                

                return 1;

            }

        };

        

        template< typename Ret, typename... Args >

        struct TFunctionTraits<Ret(*)(Args...)>

        {

            typedef Ret(*DestFunc_t)(Args...);

            static int luaFunction(lua_State* ls)

            {

                void* userData = lua_touserdata(ls, lua_upvalueindex(1));

                DestFunc_t& registedFunc = *((DestFunc_t*)userData);

                

                int n = 1;

                Ret ret = registedFunc(getArg<Args>(ls,n++)...);

                TLuaOp<Ret>::pushStack(ls,ret);

                

                return 1;

            }

        };

        

        //////////////////////////////////////////////////////

        //TLuaRegisterRouter

        //////////////////////////////////////////////////////

        template< typename Ret,typename... Args >

        struct TLuaRegisterRouter<Ret(*)(Args...)>

        {

            template< typename RegType >

            static void call(RegType* reg,Ret(*arg)(Args...),const std::string& s)

            {

                reg->defFunction(arg,s);

            }

        };

        

        template< typename Ret,typename ClassType,typename... Args >

        struct TLuaRegisterRouter<Ret(ClassType::*)(Args...)>

        {

            template< typename RegType >

            static void call(RegType* reg,Ret(ClassType::*arg)(Args...),const std::string& s)

            {

                reg->defClassFunction(arg,s);

            }

        };

        

        template< typename Ret,typename ClassType,typename... Args >

        struct TLuaRegisterRouter<Ret(ClassType::*)(Args...)const>

        {

            template< typename RegType >

            static void call(RegType* reg,Ret(ClassType::*arg)(Args...)const,const std::string& s)

            {

                reg->defClassFunction(arg,s);

            }

        };

        

        //////////////////////////////////////////////////////

        //main object LuaScript

        //////////////////////////////////////////////////////

        template< typename T >

        struct TVoidIgnore;

        

        template< typename T >

        struct TVoidIgnore

        {

            typedef T Value_t;

        };

        

        template<>

        struct TVoidIgnore<void>

        {

            typedef CppVoid Value_t;

        };

    }

    //////////////////////////////////////////////////////

    //register

    //////////////////////////////////////////////////////

#define virtual_ctor    int

#define ctor            void

    

    template< typename ClassType = detail::TOpTool,typename CtorType = void() >

    class TLuaRegister

    {

        lua_State*              _ls;

        std::string             _className;

    public:

        TLuaRegister(lua_State* ls):_ls(ls) {}

        TLuaRegister(lua_State* ls,const std::string& className,const std::string& inheritName = "" );

        

        template< typename FuncType >

        TLuaRegister& def(FuncType func,const std::string& s)

        {

            detail::TLuaRegisterRouter<FuncType>::call(this,func,s);

            return *this;

        }

        

        template< typename FuncType >

        TLuaRegister& defClassFunction(FuncType func,const std::string& funcName)

        {

            detail::LuaFunction_t classFunction = &detail::TClassFunctionTraits<FuncType>::luaFunction;

            typedef typename detail::TClassFunctionTraits<FuncType>::UserDataForFunctionInfo_t UserDataForFunction_t;

            void* userDataPtr = lua_newuserdata(_ls,sizeof(UserDataForFunction_t));

            new(userDataPtr) UserDataForFunction_t(func);

            lua_pushcclosure(_ls,classFunction,1);

            

            luaL_getmetatable(_ls,TO_METATABLE_NAME(_className));

            lua_pushstring(_ls,funcName.c_str());

            lua_pushvalue(_ls,-3);

            lua_settable(_ls,-3);

            

            lua_pop(_ls,2);

            return *this;

        }

        

        template< typename Ret >

        TLuaRegister& defClassProperty(Ret ClassType::*p, const std::string& propertyName)

        {

            typedef typename detail::TClassPropertyTraits<ClassType,Ret>::ProcessIndexFunc_t ProcessIndexFunc_t;

            typedef typename detail::TClassPropertyTraits<ClassType,Ret>::ProcessNewIndexFunc_t ProcessNewIndexFunc_t;

            ProcessIndexFunc_t processIndex       = &detail::TClassPropertyTraits<ClassType,Ret>::processIndex;

            ProcessNewIndexFunc_t processNewIndex = &detail::TClassPropertyTraits<ClassType,Ret>::processNewIndex;

            

            typedef detail::TUserDataForClassProperty<Ret ClassType::*> UserData_t;

            

            UserData_t* pu                        = (UserData_t*)lua_newuserdata(_ls,sizeof(UserData_t));

            pu->_propertyInfo._propertyPos      = p;

            int userDataIndex                   = lua_gettop(_ls);

            pu->_indexImplFunc                  = processIndex;

            pu->_newIndexImplFunc               = processNewIndex;

            pu->_propertyPos                    = (void*)(&(pu->_propertyInfo));

            

            luaL_getmetatable(_ls,detail::TLuaTypeInfo<ClassType>::getName());

            lua_pushstring(_ls,propertyName.c_str());

            lua_pushvalue(_ls,userDataIndex);

            lua_settable(_ls,-3);

            

            lua_pop(_ls,1);

            lua_remove(_ls,userDataIndex);

            return *this;

        }

        

        template< typename Func >

        TLuaRegister& defFunction(Func func,const std::string& funcName)

        {

            if(_className.empty()){

                detail::LuaFunction_t luaFunc = detail::TFunctionTraits<Func>::luaFunction;

                

                void* userDataPtr = lua_newuserdata(_ls,sizeof(func));

                new(userDataPtr) Func(func);

                

                lua_pushcclosure(_ls,luaFunc,1);

                lua_setglobal(_ls,funcName.c_str());

            }else{

                detail::LuaFunction_t luaFunc = detail::TFunctionTraits<Func>::luaFunction;

                

                void* userDataPtr = lua_newuserdata(_ls,sizeof(func));

                new(userDataPtr) Func(func);

                

                lua_pushcclosure(_ls,luaFunc,1);

                

                lua_getglobal(_ls,_className.c_str());

                lua_pushstring(_ls,funcName.c_str());

                lua_pushvalue(_ls,-3);

                lua_settable(_ls,-3);

                

                lua_pop(_ls,2);

            }

            return *this;

        }

    };

    

    template< typename ClassType,typename CtorType >

    TLuaRegister<ClassType,CtorType>::TLuaRegister(lua_State* ls,const std::string& className,const std::string& inheritName)

    :_ls(ls)

    ,_className(className)

    {

        detail::TLuaTypeInfo<ClassType>::setName(TO_METATABLE_NAME(className),TO_METATABLE_NAME(inheritName));

        

        luaL_newmetatable(ls,TO_METATABLE_NAME(className));

        int metatableIndex = lua_gettop(ls);

        if( false == inheritName.empty() ){  //有基类,设置基类

            luaL_getmetatable(ls,TO_METATABLE_NAME(inheritName));

            if(lua_istable(ls,-1)){

                lua_setfield(ls,metatableIndex,detail::INHERIT_TABLE);

            }else{

                lua_pop(ls,1);

            }

        }

        lua_pushstring(ls,"__index");

        detail::LuaFunction_t indexFunction = &detail::TMetatableRegisterImpl<ClassType>::mtIndexFunction;

        lua_pushcclosure(ls,indexFunction,0);

        lua_settable(ls,-3);

        

        lua_pushstring(ls,"getPointer");

        detail::LuaFunction_t pointerFunction = &detail::TMetatableRegisterImpl<ClassType>::getPointer;

        lua_pushcclosure(ls,pointerFunction,0);

        lua_settable(ls,-3);

        

        lua_pushstring(ls,"__newindex");

        detail::LuaFunction_t newindexFunction = &detail::TMetatableRegisterImpl<ClassType>::mtNewIndexFunction;

        lua_pushcclosure(ls,newindexFunction,0);

        lua_settable(ls,-3);

        

        detail::LuaFunction_t functionForNew = &detail::TNewTraits<ClassType,CtorType>::luaFunction;

        lua_pushcclosure(ls,functionForNew,0);

        

        lua_newtable(ls);

        lua_pushstring(ls,"new");

        lua_pushvalue(ls,-3);

        lua_settable(ls,-3);

        

        lua_setglobal(ls,className.c_str());

        

        lua_pop(ls,1);

        

        detail::LuaFunction_t functionForDelete = &detail::TDeleteTraits<ClassType>::luaFunction;

        lua_pushcclosure(ls,functionForDelete,0);

        

        lua_pushstring(ls,"delete");

        lua_pushvalue(ls,-2);

        lua_settable(ls,metatableIndex);

        

        lua_pop(ls,2);

    }

    

    class LuaScript

    {

        enum StackMinNum : int

        {

            eStackMinNum = 20

        };

        

        lua_State*  _ls;

    public:

        LuaScript()

        {

            _ls = ::luaL_newstate();

            ::luaL_openlibs(_ls);

        }

        ~LuaScript()

        {

            ::lua_close(_ls);

            _ls = nullptr;

        }

        

        void garbageCollection(int gcStep)

        {

            lua_gc(_ls, LUA_GCSTEP, gcStep);

        }

        

        operator lua_State* () { return _ls; }

        operator const lua_State* ()const { return _ls; }

        

        void dumpStack()const { detail::LuaTool::dumpStack(_ls); }

        

        //不知道为何不能用。明明是这样的

        int addPackagePath(const std::string& str)

        {

            std::string newPath = "package.path = package.path .. \"";

            if(str.empty())

                return -1;

            

            if(str[0] != ';')

                newPath += ";";

            

            newPath += str;

            

            if( str[str.length()-1] != '/' )

                newPath += "/";

            

            newPath += "?.lua\"";

            

            runString(newPath);

            

            return 0;

        }

        

        int loadFile(const std::string& fileName)throw(detail::LuaException)

        {

            if( luaL_dofile(_ls, fileName.c_str())){

                std::string err = format("LuaScript::loadFile Cannot load file<%s>%s",

                                         fileName,detail::LuaTool::dumpError(_ls));

                lua_pop(_ls, 1);

                throw detail::LuaException(std::move(err));

            }

            

            return 0;

        }

        

        void runString(const char* str)throw(detail::LuaException)

        {

            if( luaL_dostring(_ls, str)){

                std::string err = format("LuaScript::runString ::luaL_dostring failed str<%s>%s",

                                         str,detail::LuaTool::dumpError(_ls));

                lua_pop(_ls, 1);

                throw detail::LuaException(std::move(err));

            }

        }

        

        void runString(const std::string& str)

        {

            runString(str.c_str());

        }

        

        template< typename T >

        int getGlobalVariable(const std::string& fieldName,T& ret)

        {

            return getGlobalVariable<T>(fieldName.c_str(), ret);

        }

        

        template< typename T >

        int getGlobalVariable(const char* fieldName,T& ret)

        {

            int result = 0;

            

            lua_getglobal(_ls, fieldName);

            result = detail::TLuaOp<T>::getRetValue(_ls,-1,ret);

            lua_pop(_ls, 1);

            return result;

        }

        

        template< typename T >

        int setGlobalVariable(const std::string& fieldName,const T& value)

        {

            return setGlobalVariable<T>(fieldName.c_str(), value);

        }

        

        template< typename T >

        int setGlobalVariable(const char* fieldName,const T& value)

        {

            detail::TLuaOp<T>::pushStack(_ls,value);

            lua_setglobal(_ls, fieldName);

            return 0;

        }

        

        void registerRawFunction(const char* funcName,detail::LuaFunction_t func)

        {

            lua_checkstack(_ls, eStackMinNum);

            

            lua_pushcfunction(_ls, func);

            lua_setglobal(_ls, funcName);

        }

        

        void call(const char* funcName)throw(detail::LuaException)

        {

            ::lua_getglobal(_ls,funcName);

            if(::lua_pcall(_ls, 0, 0, 0) != 0){

                std::string err = format("LuaScript::call ::lua_pcall failed funcName<%s>%s",

                                         funcName,detail::LuaTool::dumpError(_ls));

                lua_pop(_ls, 1);

                throw detail::LuaException(std::move(err));

            }

        }

        

        template< typename T >

        void pushStack( const T& value)

        {

            detail::TLuaOp<T>::pushStack(_ls,value);

        }

        

        template< typename T, typename... Args >

        void pushStack( const T& value,const Args&... args)

        {

            detail::TLuaOp<T>::pushStack(_ls,value);

            pushStack(args...);

        }

        

        template< typename Ret >

        typename detail::TVoidIgnore<Ret>::Value_t call(const char* funcName)throw(detail::LuaException)

        {

            typename detail::TVoidIgnore<Ret>::Value_t ret = detail::TInitValueTrait<typename detail::TVoidIgnore<Ret>::Value_t>::value();

            

            lua_getglobal(_ls, detail::LuaStringTool::c_str(funcName));

            

            if( lua_pcall(_ls, 0, 1, 0) != 0 ){

                std::string err = format("LuaScript::call ::lua_pcall failed funcName<%s>%s",

                                         funcName,detail::LuaTool::dumpError(_ls));

                lua_pop(_ls, 1);

                throw detail::LuaException(std::move(err));

            }

            

            if( detail::TLuaOp<typename detail::TVoidIgnore<Ret>::Value_t>::getRetValue(_ls,-1,ret) ){

                lua_pop(_ls,1);

                std::string err = format("callfunc [arg%d] getRetValue failed funcName<%s>",0,funcName);

                throw detail::LuaException(std::move(err));

            }

            

            lua_pop(_ls, 1);

            

            return ret;

        }

        

        template< typename Ret,typename... Args >

        typename detail::TVoidIgnore<Ret>::Value_t call(const char* funcName,Args&&... args)throw(detail::LuaException)

        {

            typename detail::TVoidIgnore<Ret>::Value_t ret = detail::TInitValueTrait<typename detail::TVoidIgnore<Ret>::Value_t>::value();

            

            lua_getglobal(_ls, detail::LuaStringTool::c_str(funcName));

            

            pushStack(std::forward<Args>(args)...);

            

            int count = sizeof...(args);

            

            if( lua_pcall(_ls, count, 1, 0) != 0 ){

                std::string err = format("LuaScript::call ::lua_pcall failed funcName<%s>%s",

                                         funcName,detail::LuaTool::dumpError(_ls));

                lua_pop(_ls, 1);

                throw detail::LuaException(std::move(err));

            }

            

            if( detail::TLuaOp<typename detail::TVoidIgnore<Ret>::Value_t>::getRetValue(_ls,-1,ret) ){

                lua_pop(_ls,1);

                std::string err = format("callfunc [arg%d] getRetValue failed funcName<%s>",count,funcName);

                throw detail::LuaException(std::move(err));

            }

            

            lua_pop(_ls, 1);

            

            return ret;

        }

    };

}

 

#endif

 

 

posted @ 2014-12-23 16:43  Yum  阅读(178)  评论(0)    收藏  举报