• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Lua bind 和 conf 实现

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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)) \
/**/

#endif //__REPEAT_MACRO_H__

 

lua_bind.h

#ifndef __LUA_BIND_H__
#define __LUA_BIND_H__

extern "C"
{
    #include <lua.h>
}

 

#include <string>

#ifndef LOG

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

#endif //LOG

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

template <>
int lua_get_param<int>(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<bool>(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<double>(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<char const*>(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<std::string >(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<typename T>
int lua_set_result(lua_State *state, T value)
{
    LOG(ERROR, "parement type unsupport type");
    return 0;
}

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

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

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


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


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


#include "repeat_macro.h"

template<typename T>
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<typeof(&fun)> 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<typeof(&fun)> 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 <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
}

#include "lua_bind.h"

#include <sstream>
#include <string>
#include <assert.h>

#ifndef LOG

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

#endif //LOG

namespace lua
{

class LuaBase
{
public:
    bool open(char const *filename) {
        if(NULL == filename) return false;
        file_name_ = filename;

        state_ = lua_open();
        luaopen_base(state_);
        //luaopen_io(state_);
        //luaopen_string(state_);
        //luaopen_math(state_);
        if (luaL_loadfile(state_, file_name_.c_str())) {
            LOG(ERROR, "cannot load configuration file: %s", file_name_.c_str());
            close();
            return false;
        }
        return true;
    }

    typedef int bind_type(lua_State *);

    bool registry(char const *name, bind_type fun) {
        if(NULL==name || NULL == state_) return false;
        lua_pushcfunction(state_, fun);
        lua_setglobal(state_,  name);
        return true;
    }

    bool load()
    {
      if(NULL == state_) return false;
      if(lua_pcall(state_, 0, 0, 0)){
         LOG(ERROR, "cannot run configuration file: %s", file_name_.c_str());
         close();
         return false;
      }
      return true;
    }


    void close() {
        if(state_) lua_close(state_);
        state_ = NULL;
    }

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

class LuaConf: public LuaBase
{
public:
    template <typename T>
    T get(char const* name){
        if(NULL==name || NULL == state_) return T();
        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);
        lua_pop(state_, -1);
        std::istringstream in(value, std::istringstream::in);
        T ret;
        in>>ret;
        return ret;
    }

};

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

        int result = (int)lua_tonumber(state_, -1);
        lua_pop(state_, -1);
        return result;
    }

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

        double result = lua_tonumber(state_, -1);
        lua_pop(state_, -1);
        return result;
    }

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

        std::string result =  lua_tostring(state_, -1);
        lua_pop(state_, -1);
        return result;
    }

};

#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 <stdio.h>
#include <string>

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<int>("a");
    printf("a=%d\n", a);
    std::string b = conf.get<std::string>("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人参与评论

请发表评论

全部评论

专题导读
上一篇:
VS Code 与lua使用简介发布时间:2022-07-22
下一篇:
【RPA插件开发】使用 Lua 扩展 UiBot 的功能发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap