zoukankan      html  css  js  c++  java
  • 一种C函数到Lua的封装

    Lua也可以调用C函数,只是以更加崎岖的方式——通过一个私有栈来传递参数和返回值。提供给Lua API的C函数都是这个样子的:

    static int sum(lua_State *L)
    {
        int a = lua_tonumber(L, -1);
        int b = lua_tonumber(L, -2);
        lua_pop(L, 2);
        lua_pushnumber(L, a + b);
        return 1; /* return one value. */
    }

    Lua将其定义为:

    typedef int (*lua_CFunction)(lua_State *L);

    还须在全局栈如此注册C函数:

    lua_pushcfunction(L, sum);
    lua_setglobal(L, "sum");

    看了些开源的Lua封装库,对此也作了封装。受此启发,笔者也为自己的Lucy库增加了C函数封装。

    承之前的设计思路,用lucy_Data类型表示Lua数据,那么要让Lua调用的C函数应该是这样的:

    static lucy_List sum(const lucy_List *args)
    {
        int a = args->datas_[0].cntnt_.num_;
        int b = args->datas_[1].cntnt_.num_;
        lucy_Data r = lucy_Num(a + b);
        return lucy_GetList(1, &r);
    }

    不妨定义这样的C函数为:

    typedef lucy_List (*lucy_CFuncWithList)(const lucy_List *args);

    易写一个函数,作为lucy_CFuncWithList与lua_CFunction的翻译:

    void lucy_CallCFunc(lua_State *state, lucy_CFuncWithList cfunc, int rc, int ac);

    须要写一个宏,让其产生lua_CFunction类型的函数:

    #define lucy_GenLuaCFunction(cfunc, rc, ac) \
    static int LUA_CFUNCTION_NAME(cfunc)(lua_State *state) \
    {\
        lucy_CallCFunc(state, cfunc, rc, ac);\
        return rc;\
    }

    最后写一个宏注册C函数:

    #define lucy_SetCFunc(file, name, cfunc) \
        lua_pushcfunction((file)->state_, LUA_CFUNCTION_NAME(cfunc));\
        lua_setglobal((file)->state_, name)

    这样设计的好处依然是,Lua数据在C函数中视作第一类型——比如可以在被Lua调用的C函数中调用Lua函数。

    比如有如下的Lua代码:

    Do(3, print, "Hello world!")

    这行代码希望Do是一个C函数,通过Lua函数print,输出3次“Hello world!”。

    通过Lucy可以这么做:

    static lucy_List Do(const lucy_List *args)
    {
        int times = args->datas_[0].cntnt_.num_;
        const lucy_Data *func = args->datas_ + 1;
        const lucy_Data *str = args->datas_ + 2;
        int i;
        for (i=0; i<times; ++i) {
            lucy_Call(func, 0, 1, str);
        }
    
        return lucy_GetList(0);
    }
    
    lucy_GenLuaCFunction(Do, 0, 3);
    
    int main()
    {
        lucy_File file = lucy_CreateFile();
        lucy_OpenFile(&file, "/Code/a.lua");
        lucy_SetCFunc(&file, "Do", Do);
        lucy_Run(&file);
        lucy_CloseFile(&file);
        return 0;
    }

    输出结果:

    更新已push至:https://github.com/chncwang/Lucy

  • 相关阅读:
    汉诺塔难题
    函数的两种调用方式

    汉诺塔难题
    汉诺塔难题

    python中对小数取整
    linux中部署apache服务(http服务或者web服务)
    python中如何判断变量类型
    python中求余数
  • 原文地址:https://www.cnblogs.com/qswang/p/2661857.html
Copyright © 2011-2022 走看看