Lua bind for C 和 conf 实现

Lua ,语法简单(极像javascript), 移植性好(纯C实现), 启动速度快,空间占用小, 真不愧是潜入式脚本语言之王。

本人想拿它来做 配置文件(conf),也像加一点IoC, 就是配置脚本可以调用主程序的函数。

实现如下:

repeat_macro.h

#ifndef __REPEAT_MACRO_H__
#define __REPEAT_MACRO_H__

// concatenation
#define CAT(a, b) PRIMITIVE_CAT(a, b)
#define PRIMITIVE_CAT(a, b) a ## b

// binary intermediate split
#define SPLIT(i, im) PRIMITIVE_CAT(SPLIT_, i)(im)
#define SPLIT_0(a, b) a
#define SPLIT_1(a, b) b

// saturating increment and decrement
#define DEC(x) SPLIT(0, PRIMITIVE_CAT(DEC_, x))
#define INC(x) SPLIT(1, PRIMITIVE_CAT(DEC_, x))

#define DEC_0 0, 1
#define DEC_1 0, 2
#define DEC_2 1, 3
#define DEC_3 2, 4
#define DEC_4 3, 5
#define DEC_5 4, 6
#define DEC_6 5, 7
#define DEC_7 6, 8
#define DEC_8 7, 9
#define DEC_9 8, 10
#define DEC_10 9, 11
#define DEC_11 10, 12
#define DEC_12 11, 13
#define DEC_13 12, 14
#define DEC_14 13, 15
#define DEC_15 14, 15

// bit complement
#define COMPL(bit) PRIMITIVE_CAT(COMPL_, bit)
#define COMPL_0 1
#define COMPL_1 0

// nullary parentheses detection
#define IS_NULLARY(x) SPLIT(0, CAT(IS_NULLARY_R_, IS_NULLARY_C x))
#define IS_NULLARY_C() 1
#define IS_NULLARY_R_1 1, ~
#define IS_NULLARY_R_IS_NULLARY_C 0, ~

// boolean conversion
#define BOOL(x) COMPL(IS_NULLARY(PRIMITIVE_CAT(BOOL_, x)))
#define BOOL_0 ()

// recursion backend
#define EXPR(s) PRIMITIVE_CAT(EXPR_, s)
#define EXPR_0(x) x
#define EXPR_1(x) x
#define EXPR_2(x) x
#define EXPR_3(x) x
#define EXPR_4(x) x
#define EXPR_5(x) x
#define EXPR_6(x) x
#define EXPR_7(x) x
#define EXPR_8(x) x
#define EXPR_9(x) x
#define EXPR_10(x) x
#define EXPR_11(x) x
#define EXPR_12(x) x
#define EXPR_13(x) x
#define EXPR_14(x) x
#define EXPR_15(x) x

// bit-oriented if control structure
#define IIF(bit) PRIMITIVE_CAT(IIF_, bit)
#define IIF_0(t, f) f
#define IIF_1(t, f) t

// number-oriented if control structure
#define IF(cond) IIF(BOOL(cond))

// emptiness abstraction
#define EMPTY()

// 1x and 2x deferral macros
#define DEFER(macro) macro EMPTY()
#define OBSTRUCT() DEFER(EMPTY)()

// argument list eater
#define EAT(size) PRIMITIVE_CAT(EAT_, size)
#define EAT_0()
#define EAT_1(a)
#define EAT_2(a, b)
#define EAT_3(a, b, c)
#define EAT_4(a, b, c, d)
#define EAT_5(a, b, c, d, e)
#define EAT_6(a, b, c, d, e, f)
#define EAT_7(a, b, c, d, e, f, g)
#define EAT_8(a, b, c, d, e, f, g, h)
#define EAT_9(a, b, c, d, e, f, g, h, i)
#define EAT_10(a, b, c, d, e, f, g, h, i, j)
#define EAT_11(a, b, c, d, e, f, g, h, i, j, k)

// comma abstractions
#define COMMA() ,
#define COMMA_IF(n) IF(n)(COMMA, EMPTY)()

// repetition construct
#define REPEAT(s, count, macro, data) /
EXPR(s)(REPEAT_I(INC(s), INC(s), count, macro, data)) /
/**/
#define REPEAT_INDIRECT() REPEAT_I
#define REPEAT_I(s, o, count, macro, data) /
IF(count)(REPEAT_II, EAT(6))(OBSTRUCT(), s, o, DEC(count), macro, data) /
/**/
#define REPEAT_II(_, s, o, count, macro, data) /
EXPR(s) _(REPEAT_INDIRECT _()( /
INC(s), o, count, macro, data /
)) /
EXPR OBSTRUCT()(o)(macro OBSTRUCT()(o, count, data)) /
/**/

/*
// original example
#define COPY_M(s, v, _) s1.CAT(n, INC(v)) = s2.CAT(i, INC(v));
#define COPY(n) EXPR(0)(REPEAT(0, n, COPY_M, ~))

COPY(3)

// multidimensional example (template template parameters)
#define FIXED(s, n, text) COMMA_IF(n) text
#define TTP(s, n, _) /
COMMA_IF(n) template class T ## n /
/** /

#define TEMPLATE_TEMPLATE(n) EXPR(0)(REPEAT(0, n, TTP, ~))

TEMPLATE_TEMPLATE(3)
*/

#endif //__REPEAT_MACRO_H__

 

lua_bind.h

 

#ifndef __LUA_BIND_H__
#define __LUA_BIND_H__

extern "C"
{
    #include
}

 

#include

#ifndef LOG

#define ENABLE_LUA_BIND_H_LOG
#include
#define LOG(level, format, ...) /
    fprintf(stderr, "[%s][%s][%d]: " format "/n", #level, __FILE__, int(__LINE__), ##__VA_ARGS__)

#endif //LOG

template
T lua_get_param(lua_State *state, int index)
{
    LOG(ERROR, "parement type unsupport type");
    return T();
}

template <>
int lua_get_param (lua_State *state, int index)
{
    if (!lua_isnumber(state, index)) {
        LOG(ERROR, "lua argument should be a number/n");
        return 0;
    }

    return (int)lua_tonumber(state, index);
}


template <>
bool lua_get_param (lua_State *state, int index)
{
    if (!lua_isboolean(state, index)){
        LOG(ERROR, "lua argument should be a boolean/n");
        return 0;
    }

    return (bool)lua_toboolean(state, index);
}


template <>
double lua_get_param (lua_State *state, int index)
{
    if (!lua_isnumber(state, index)) {
        LOG(ERROR, "lua argument should be a number/n");
        return 0;
    }

    return lua_tonumber(state, index);
}


template <>
char const * lua_get_param (lua_State *state, int index)
{
    if (!lua_isstring(state, index)){
        LOG(ERROR, "lua argument should be a string/n");
        return "";
    }

    return lua_tostring(state, index);
}


template <>
std::string lua_get_param (lua_State *state, int index)
{
    if (!lua_isstring(state, index)){
        LOG(ERROR, "lua argument should be a string/n");
        return std::string();
    }

    return std::string(lua_tostring(state, index));
}

 

template
int lua_set_result(lua_State *state, T value)
{
    LOG(ERROR, "parement type unsupport type");
    return 0;
}

template <>
int lua_set_result (lua_State *state, int value)
{
    lua_pushnumber(state, double(value));
    return 1;
}

template <>
int lua_set_result (lua_State *state, bool value)
{
    lua_pushboolean(state, value);
    return 1;
}

template <>
int lua_set_result (lua_State *state, double value)
{
    lua_pushnumber(state, value);
    return 1;
}


template <>
int lua_set_result (lua_State *state, char const * value)
{
    if(value) {
        lua_pushstring(state, value);
    } else {
        lua_pushstring(state, "");
    }
    return 1;
}


template <>
int lua_set_result (lua_State *state, std::string value)
{
    lua_pushstring(state, value.c_str());
    return 1;
}


#include "repeat_macro.h"

template
class function_type_info
{
    public:
        typedef T result_type;
};

#define TEMPLATE_PARAM_TYPE(s, v, arg) COMMA_IF(v) typename CAT(arg, v)
#define TEMPLATE_PARAM_TYPE_LIST(num) EXPR(0)(REPEAT(0, num, TEMPLATE_PARAM_TYPE, arg))

#define DEF_FUN_PARAM_TYPE(s, v, arg) typedef CAT(arg, v) CAT(CAT(arg, v), _type) ;
#define ALL_DEF_FUN_PARAM_TYPE(num) EXPR(0)(REPEAT(0, num, DEF_FUN_PARAM_TYPE, arg))

#define GET_FUN_PARAM_TYPE(s, v, arg) COMMA_IF(v) CAT(arg, INC(v))
#define GET_FUN_PARAM_TYPE_LIST(num) EXPR(0) (REPEAT(0, num, GET_FUN_PARAM_TYPE, arg))

#define DEF_FUNCTION_TYPE_INFO(_, num, arg) /
template< TEMPLATE_PARAM_TYPE_LIST(INC(num)) > /
class function_type_info< arg0 (*)( GET_FUN_PARAM_TYPE_LIST(num) ) > /
{/
    public:/
    ALL_DEF_FUN_PARAM_TYPE(INC(num))/
    typedef arg0 result_type;/
};


DEF_FUNCTION_TYPE_INFO(_, 0, arg)
DEF_FUNCTION_TYPE_INFO(_, 1, arg)
DEF_FUNCTION_TYPE_INFO(_, 2, arg)
DEF_FUNCTION_TYPE_INFO(_, 3, arg)
DEF_FUNCTION_TYPE_INFO(_, 4, arg)
DEF_FUNCTION_TYPE_INFO(_, 5, arg)
DEF_FUNCTION_TYPE_INFO(_, 6, arg)
DEF_FUNCTION_TYPE_INFO(_, 7, arg)
DEF_FUNCTION_TYPE_INFO(_, 8, arg)
DEF_FUNCTION_TYPE_INFO(_, 9, arg)
DEF_FUNCTION_TYPE_INFO(_, 10, arg)
DEF_FUNCTION_TYPE_INFO(_, 11, arg)
DEF_FUNCTION_TYPE_INFO(_, 12, arg)
DEF_FUNCTION_TYPE_INFO(_, 13, arg)
DEF_FUNCTION_TYPE_INFO(_, 14, arg)


#define LUA_PARAM_TYPE(functor,n)  CAT(CAT(functor::arg, n),_type)
#define GET_PARAM_IN(s, v, functor)  LUA_PARAM_TYPE(functor, v) CAT(arg, v) = lua_get_param< LUA_PARAM_TYPE(functor, v) >(state, v);
#define GET_PARAM_FUN(n, functor) EXPR(0)(REPEAT(1, INC(n), GET_PARAM_IN, functor))


#define LUA_CALL_ARG_IN(s, v, arg) COMMA_IF(v) CAT(arg, INC(v))
#define LUA_CALL_FUN_ARG(n, arg) EXPR(0)(REPEAT(0, n, LUA_CALL_ARG_IN, arg))

#define LUA_BIND_NAME(fun, num) CAT(CAT(__lua_bind_, fun), num)
#define DEF_LUA_BIND(fun, num)/
    int LUA_BIND_NAME(fun, num) (lua_State *state){ /
        typedef function_type_info functor_info_type; /
        GET_PARAM_FUN(num, functor_info_type) /
        typeof(fun(LUA_CALL_FUN_ARG(num, arg))) result = fun(LUA_CALL_FUN_ARG(num, arg));/
        int ret = lua_set_result(state, result); /
        return ret;/
    }


#define DEF_LUA_BIND_VOID(fun, num)/
    int LUA_BIND_NAME(fun, num) (lua_State *state){ /
        typedef function_type_info functor_info_type; /
        GET_PARAM_FUN(num, functor_info_type) /
        fun(LUA_CALL_FUN_ARG(num, arg));/
        return 0;/
    }


#ifdef ENABLE_LUA_BIND_H_LOG
#undef LOG
#undef ENABLE_LUA_BIND_H_LOG
#endif //ENABLE_LUA_BIND_H_LOG

#endif //__LUA_BIND_H__

lua_conf.hpp

 

#ifndef __LUA_CONF_H__
#define __LUA_CONF_H__

extern "C"
{
    #include
    #include
    #include
}

#include "lua_bind.h"

#include
#include
#include

#ifndef LOG

#define ENABLE_LUA_CONF_H_LOG
#include
#define LOG(level, format, ...) /
    fprintf(stderr, "[%s][%s][%d]: " format "/n", #level, __FILE__, int(__LINE__), ##__VA_ARGS__)

#endif //LOG

namespace lua
{

class LuaBase
{
public:
    void open(char *filename) {
        if(filename) {
            file_name_ = filename;
        }

        lua_State *L = lua_open();
        luaopen_base(L);
        //luaopen_io(L);
        //luaopen_string(L);
        //luaopen_math(L);
        if (luaL_loadfile(L, file_name_.c_str())) {
            LOG(ERROR, "cannot load configuration file: %s", file_name_.c_str());
            lua_close(L);
        }
        state_ = L;
    }


    void close() {
            lua_close(state_);
    }

    lua_State *state_;
    std::string file_name_;
};

class LuaConf: public LuaBase
{
public:
    typedef int bind_type(lua_State *);
    void registry(char const *name, bind_type fun) {
        lua_pushcfunction(state_, fun);
        if(NULL == name) name ="";
        lua_setglobal(state_,  name);
    }

    void load()
    {
      if(lua_pcall(state_, 0, 0, 0)){
         LOG(ERROR, "cannot run configuration file: %s", file_name_.c_str());
         lua_close(state_);
      }
    }

    template
    T get(char const* name){
        assert(name);
        lua_getglobal(state_, name);
        if (!lua_isstring(state_, -1)){
            LOG(ERROR, "should be a string/n");
            return T();
        }

        std::string value = lua_tostring(state_, -1);
        std::istringstream in(value, std::istringstream::in);
        T ret;
        in>>ret;
        return ret;
    }

};

    template <>
    int LuaConf::get (char const* name){
        assert(name);
        lua_getglobal(state_, name);
        if (!lua_isnumber(state_, -1)) {
            LOG(ERROR, "should be a number/n");
            return 0;
        }

        return (int)lua_tonumber(state_, -1);
    }

    template <>
    double LuaConf::get (char const* name) {
        assert(name);
        lua_getglobal(state_, name);
        if (!lua_isnumber(state_, -1)) {
            LOG(ERROR, "should be a number/n");
            return 0;
        }

        return lua_tonumber(state_, -1);
    }

    template <>
    std::string LuaConf::get (char const* name) {
        assert(name);
        lua_getglobal(state_, name);
        if (!lua_isstring(state_, -1)) {
            LOG(ERROR, "should be a string/n");
            return std::string();
        }

        return lua_tostring(state_, -1);
    }

};

#ifdef ENABLE_LUA_CONF_H_LOG
#undef LOG
#undef ENABLE_LUA_CONF_H_LOG
#endif //ENABLE_LUA_CONF_H_LOG

#endif //__LUA_CONF_H__

 

lua_conf.test.cpp

#include "lua_conf.hpp"
#include
#include

int say(char const *name) {
    printf("i say %s", name);
    return 1;
}

DEF_LUA_BIND(say, 1)

int main()
{
    lua::LuaConf conf;
    conf.open("1.lua");
    conf.registry("say", LUA_BIND_NAME(say, 1));
    conf.load();
    int a = conf.get ("a");
    printf("a=%d/n", a);
    std::string b = conf.get ("b");
    printf("b=%s/n", b.c_str());
    return 0;
}

makefile

lua_conf.test: lua_conf.test.cpp
    g++ -g -I./ lua_conf.test.cpp -L./ -llua -o lua_conf.test

clean:
    rm lua_conf.test

1.lua

a=4

b=[[good girl]]

say(“hello”)

结果

i say hello

a=4

b=good girl

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值