神のような狙撃Luaの気持ち悪い操作(小さな応用ロジックを書くのにスタックに出入りする気持ち悪い細部を管理しなければならない.あまりにも二番目だから、兄はやることにした)
16599 ワード
/********************************************************************
author : Clark/
created : 2013-5-8
purpose :
*********************************************************************/
#pragma once
//
struct RefClassType
{
//
virtual long GetType() = 0;
};
//
template< class Base, int TYPE_ID >
struct GetClassTypeEx: public Base
{
//
virtual long GetType(){ return TYPE_ID; }
};
// ID
struct RefClassID
{
//
virtual long GetID() = 0;
};
// ID
template< class Base >
struct GetClassIDEx: public Base
{
public:
GetClassIDEx(const long _id):ID(_id){}
//
virtual long GetID(){ return ID; }
private:
const long ID;
};
/********************************************************************
author : Clark/
created : 2013-5-8
purpose : LK_Typelist
*********************************************************************/
#pragma once
//-----------------------------------------------------------------------------------------------------------------------------
#define TL_1(T1) \
LK_Typelist<T1, LK_NULL_TYPE>
#define TL_2(T1, T2) \
LK_Typelist<T1, TL_1(T2) >
#define TL_3(T1, T2, T3) \
LK_Typelist<T1, TL_2(T2, T3) >
#define TL_4(T1, T2, T3, T4) \
LK_Typelist<T1, TL_3(T2, T3, T4) >
#define TL_5(T1, T2, T3, T4, T5) \
LK_Typelist<T1, TL_4(T2, T3, T4, T5) >
#define TL_6(T1, T2, T3, T4, T5, T6) \
LK_Typelist<T1, TL_5(T2, T3, T4, T5, T6) >
#define TL_7(T1, T2, T3, T4, T5, T6, T7) \
LK_Typelist<T1, TL_6(T2, T3, T4, T5, T6, T7) >
#define TL_8(T1, T2, T3, T4, T5, T6, T7, T8) \
LK_Typelist<T1, TL_7(T2, T3, T4, T5, T6, T7, T8) >
//-----------------------------------------------------------------------------------------------------------------------------
//
struct LK_NULL_TYPE{};
template <class T, class U>
struct LK_Typelist
{
typedef T Head;
typedef U Tail;
};
//
template< class TList >
struct LK_GetLength
{
enum { Ret = 1 + LK_GetLength< TList::Tail >::Ret };
};
template<>
struct LK_GetLength<LK_NULL_TYPE>
{
enum { Ret = 0 };
};
//
template< class TList, unsigned int index >
struct LK_TypeAt;
template< class Head, class Tail >
struct LK_TypeAt< LK_Typelist<Head, Tail>, 0 >
{
typedef Head Result;
};
template< class Head, class Tail, unsigned int i >
struct LK_TypeAt< LK_Typelist<Head, Tail>, i >
{
typedef typename LK_TypeAt<Tail, i - 1>::Result Result;
};
/********************************************************************
author : Clark/
created : 2013-5-8
purpose : Lua
*********************************************************************/
#pragma once
#include "RefClassHelper.h"
#include <Windows.h>
#include <vector>
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
using namespace std;
//
struct LuaNumber : public GetClassTypeEx<RefClassType, 1>
{
LuaNumber(){ val = 0;}
LuaNumber( double _val ){ val = _val; }
void operator = (double _val){ val = _val; }
double val;
};
//
struct LuaString : public GetClassTypeEx<RefClassType, 2>
{
LuaString(){ val[0] = 0; }
LuaString( const char*_val ){ val[0] = 0; if( NULL != _val ) lstrcpyn(val, _val, sizeof(val)); }
void operator = (const char *_val){ val[0] = 0; if( NULL != _val ) lstrcpyn(val, _val, sizeof(val)); }
char val[1024];
};
//
bool CallLFun(lua_State *_L, const char* _lua_fun_name, vector< RefClassType* >* _in_pars = nullptr, vector< RefClassType* >* _out_pars = nullptr)
{
//
lua_getglobal(_L, _lua_fun_name);
int in_len = ( nullptr != _in_pars) ? _in_pars->size() : 0;
int out_len = ( nullptr != _out_pars) ? _out_pars->size() : 0;
if( nullptr != _in_pars)
{
in_len = _in_pars->size();
for( int i=0; i<in_len; i++)
{
if( 1 == (*_in_pars)[i]->GetType() )
lua_pushnumber(_L, ((LuaNumber*)(*_in_pars)[i])->val);
else
lua_pushstring(_L, ((LuaString*)(*_in_pars)[i])->val);
}
}
if( 0 != lua_pcall(_L, in_len, out_len, 0) ){ goto FUN_ERROR; }
//
if( out_len != lua_gettop(_L) ) { goto FUN_ERROR; }
if( nullptr != _out_pars )
{
//
for (int i = out_len - 1; i >= 0; i--)
{
if( 1 == (*_out_pars)[i]->GetType())
{
if (!lua_isnumber(_L, -1)){ goto FUN_ERROR;}
*((LuaNumber*)(*_out_pars)[i]) = (double)lua_tonumber(_L, -1);
lua_pop(_L, 1);
}
else
{
if (!lua_isstring(_L, -1)){ goto FUN_ERROR;}
*((LuaString*)(*_out_pars)[i]) = (const char *)lua_tostring(_L, -1);
lua_pop(_L, 1);
}
}
}
return true;
FUN_ERROR:
//printf("Error in %s", _lua_fun_name);
lua_settop(_L, 0);
return false;
}
/*
vector<RefClassType*> in_pars;
vector<RefClassType*> out_pars;
LuaString val1("1");
in_pars.push_back(&val1);
LuaString val2("2");
in_pars.push_back(&val2);
LuaNumber oval1(0);
out_pars.push_back(&oval1);
LuaString oval2("");
out_pars.push_back(&oval2);
*/
/********************************************************************
author : Clark/
created : 2013-5-8
purpose : C LUA ( Lua , “ ” !)
*********************************************************************/
#pragma once
#include "LK_TypeList.h"
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
//-----------------------------------------------------------------------------------------------------------------------------
template< class _Ret, class _TypeList, int >
struct PopPar2CAction{};
//0
template<class _Ret, class _TypeList>
struct PopPar2CAction<_Ret, _TypeList, 0>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { return fun(); }
};
//1
#define INIT_LUA_VL_1(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_1 = NULL; \
Lua_GetPar(lua_stack_val_1, _L, I+1);
#define GET_LUA_VL_1() \
lua_stack_val_1
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 1>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { INIT_LUA_VL_1( _TypeList, 0, L ); return fun( GET_LUA_VL_1() ); }
};
//2
#define INIT_LUA_VL_2(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_2 = NULL; \
Lua_GetPar(lua_stack_val_2, _L, I+1); \
INIT_LUA_VL_1(LTYP_LIST, I+1, _L)
#define GET_LUA_VL_2() \
lua_stack_val_2, GET_LUA_VL_1()
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 2>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun)
{
INIT_LUA_VL_2( _TypeList, 0, L );
return fun( GET_LUA_VL_2() );
}
};
//3
#define INIT_LUA_VL_3(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_3 = NULL; \
Lua_GetPar(lua_stack_val_3, _L, I+1); \
INIT_LUA_VL_2(LTYP_LIST, I+1, _L)
#define GET_LUA_VL_3() \
lua_stack_val_3, GET_LUA_VL_2()
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 3>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { INIT_LUA_VL_3( _TypeList, 0, L ); return fun( GET_LUA_VL_3() ); }
};
//4
#define INIT_LUA_VL_4(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_4 = NULL; \
Lua_GetPar(lua_stack_val_4, _L, I+1); \
INIT_LUA_VL_3(LTYP_LIST, I+1, _L)
#define GET_LUA_VL_4() \
lua_stack_val_4, GET_LUA_VL_3()
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 4>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { INIT_LUA_VL_4( _TypeList, 0, L ); return fun( GET_LUA_VL_4() ); }
};
//5
#define INIT_LUA_VL_5(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_5 = NULL; \
Lua_GetPar(lua_stack_val_5, _L, I+1); \
INIT_LUA_VL_4(LTYP_LIST, I+1, _L)
#define GET_LUA_VL_5() \
lua_stack_val_5, GET_LUA_VL_4()
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 5>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { INIT_LUA_VL_5( _TypeList, 0, L ); return fun( GET_LUA_VL_5() ); }
};
//6
#define INIT_LUA_VL_6(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_6 = NULL; \
Lua_GetPar(lua_stack_val_6, _L, I+1); \
INIT_LUA_VL_5(LTYP_LIST, I+1, _L)
#define GET_LUA_VL_6() \
lua_stack_val_6, GET_LUA_VL_5()
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 6>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { INIT_LUA_VL_6( _TypeList, 0, L ); return fun( GET_LUA_VL_6() ); }
};
//7
#define INIT_LUA_VL_7(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_7 = NULL; \
Lua_GetPar(lua_stack_val_7, _L, I+1); \
INIT_LUA_VL_6(LTYP_LIST, I+1, _L)
#define GET_LUA_VL_7() \
lua_stack_val_7, GET_LUA_VL_6()
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 7>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { INIT_LUA_VL_7( _TypeList, 0, L ); return fun( GET_LUA_VL_7() ); }
};
//8
#define INIT_LUA_VL_8(LTYP_LIST, I, _L) \
LK_TypeAt< LTYP_LIST, I >::Result lua_stack_val_8 = NULL; \
Lua_GetPar(lua_stack_val_8, _L, I+1); \
INIT_LUA_VL_7(LTYP_LIST, I+1, _L)
#define GET_LUA_VL_8() \
lua_stack_val_8, GET_LUA_VL_7()
template<class _Ret, class _TypeList >
struct PopPar2CAction<_Ret, _TypeList, 8>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun) { INIT_LUA_VL_8( _TypeList, 0, L ); return fun( GET_LUA_VL_8() ); }
};
//---------------------------------- ----------------------------------
template<class _Type>
struct Lua_IsType
{
bool operator()(lua_State *L, int pos){ return false; }
};
template<>
struct Lua_IsType< double >
{
bool operator()(lua_State *L, int pos){ return ( lua_isnumber(L, pos)?true:false ); }
};
template<>
struct Lua_IsType< long >
{
bool operator()(lua_State *L, int pos){ return ( lua_isnumber(L, pos)?true:false ); }
};
template<>
struct Lua_IsType< int >
{
bool operator()(lua_State *L, int pos){ return ( lua_isnumber(L, pos)?true:false ); }
};
template<>
struct Lua_IsType< char* >
{
bool operator()(lua_State *L, int pos){ return ( lua_isstring(L, pos)?true:false ); }
};
//---------------------------------- Lua ----------------------------------
static bool Lua_GetPar(char*& _val, lua_State* _L, int _index)
{
_val = ((char*) lua_tostring(_L,_index));
return true;
}
static bool Lua_GetPar(long& _val, lua_State* _L, int _index)
{
_val = ((long) lua_tonumber(_L,_index));
return true;
}
static bool Lua_GetPar(bool& _val, lua_State* _L, int _index)
{
_val = lua_tonumber(_L, _index) != 0;
return true;
}
static bool Lua_GetPar(int& _val, lua_State* _L, int _index)
{
_val = ((int) lua_tonumber(_L,_index));
return true;
}
static bool Lua_GetPar(double& _val, lua_State* _L, int _index)
{
_val = ((int) lua_tonumber(_L,_index));
return true;
}
//---------------------------------- Lua ----------------------------------
template< class _Type >
static void Lua_PushPar(lua_State* _L, _Type _val)
{
lua_pushnumber(_L, (lua_Number)_val);
}
static void Lua_PushPar(lua_State* _L, const char* _val)
{
if (_val == NULL)
lua_pushnil(_L);
else
lua_pushstring(_L,_val);
}
//---------------------------------- ----------------------------------
template< class _TypeList >
class CheckLuaType
{
protected:
template< class TList >
struct CheckAllType;
template<>
struct CheckAllType<LK_NULL_TYPE>
{
bool operator()(lua_State *L, int index)
{
return (lua_gettop(L)<abs(index) ? true:false);
}
};
template <class T, class U>
struct CheckAllType< LK_Typelist<T, U> >
{
bool operator()(lua_State *L, int index = 1)
{
if( !Lua_IsType<T>()(L, index) )
return false;
return CheckAllType<U>()(L, index+1);
}
};
};
//---------------------------------- C C ----------------------------------
template< class _Ret, class _TypeList >
struct Par2CAction: public CheckLuaType<_TypeList>
{
template< class _Fun >
_Ret operator()(lua_State *L, _Fun fun)
{
#ifdef _DEBUG
//
if(lua_gettop(L) != LK_GetLength<_TypeList>::Ret )
{
lua_pushstring(L, "Incorrect argument number!");
lua_error(L);
}
if(!CheckAllType< _TypeList >()(L))
{
lua_pushstring(L, "Incorrect argument!");
lua_error(L);
}
#endif
PopPar2CAction<_Ret, _TypeList, LK_GetLength<_TypeList>::Ret> run;
_Ret ret = run(L, fun);
Lua_PushPar(L,ret);
return ret;
}
};
template< class _TypeList >
struct Par2CAction<void, _TypeList>: public CheckLuaType<_TypeList>
{
template< class _Fun >
void operator()(lua_State *L, _Fun fun)
{
#ifdef _DEBUG
//
if(lua_gettop(L) != LK_GetLength<_TypeList>::Ret )
{
lua_pushstring(L, "Incorrect argument number!");
lua_error(L);
}
if( !CheckAllType< _TypeList >()(L))
{
lua_pushstring(L, "Incorrect argument!");
lua_error(L);
}
#endif
PopPar2CAction<void, _TypeList, LK_GetLength<_TypeList>::Ret> run;
run(L, fun);
Lua_PushPar(L,0);
}
};
// C LUA
template< int v, class _Fun, class _Stack >
class RegApiForLua
{
public:
static void Register(lua_State *L, const char* _lua_fun_name, _Fun _c_fun)
{
mp_c_fun = &_c_fun;
lua_register( L, _lua_fun_name, (&RegApiForLua<v,_Fun,_Stack>::API) );
}
private:
static int API(lua_State *L)
{
m_par2caction(L, *mp_c_fun);
return 1;
}
static _Stack m_par2caction;
static _Fun *mp_c_fun;
};
template< int v, class _Fun, class _Stack >
_Stack RegApiForLua<v,_Fun,_Stack>::m_par2caction;
template< int v, class _Fun, class _Stack >
_Fun* RegApiForLua<v,_Fun,_Stack>::mp_c_fun = nullptr;
/*
RegApiForLua<0, decltype(test), Par2CAction<void, TL_1(int)> >::Register(L, "C_API", test);
RegApiForLua<1, decltype(test1), Par2CAction<int, TL_2(char*, int)> >::Register(L, "C_API1", test1);
*/
#include <iostream>
#include "RegCFun.h"
#include "CallLFun.h"
using namespace std;
#pragma comment(lib,"lua5.1.lib")
void test( int p1 )
{
printf("test: %d
", p1);
}
int test1( const char* p1, int p2 )
{
printf("test1: %s, %d
", p1, p2);
return p2*2;
}
int main()
{
lua_State *L = lua_open();
luaL_openlibs(L);
RegApiForLua<0, decltype(test), Par2CAction<void, TL_1(int)> >::Register(L, "C_API", test);
RegApiForLua<1, decltype(test1), Par2CAction<int, TL_2(char*, int)> >::Register(L, "C_API1", test1);
vector<RefClassType*> in_pars;
vector<RefClassType*> out_pars;
LuaString val1("C_par1");
in_pars.push_back(&val1);
LuaString val2("C_par2");
in_pars.push_back(&val2);
LuaNumber oval1;
out_pars.push_back(&oval1);
LuaString oval2;
out_pars.push_back(&oval2);
if (luaL_dofile(L, "test.lua"))
nullptr;
CallLFun(L, "LuaMain", &in_pars, &out_pars);
lua_close(L);
system("pause");
}
function LuaMain(p1, p2)
print("p1", p1, "p2", p2)
C_API(1000)
local ret = C_API1("call C_API1", 5)
print( ret )
return ret, "LuaMain "
end