//
// 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