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

    一种Lua到C的封装

     

    在Lua的官方C API中,Lua与C通过一个虚拟栈来交互数据。例如有个a.lua的文件中有求和函数:

    function sum(a, b)
        return a + b
    end

    要在C代码中打开lua文件,并调用求和函数,大致要这样写:

    复制代码
    lua_State *s = luaL_newstate();
    luaL_openlibs(s);
    luaL_loadfile(s, "a.lua");
    lua_getglobal(s, "sum");
    lua_pushinteger(s, 1234);
    lua_pushinteger(s, 4321);
    lua_pcall(s, 2, 1, 0);
    int sum = lua_tointeger(s, -1); /* sum = 5555 */
    lua_pop(s, 1);
    lua_close(s);
    复制代码

    可以想见官方API的设计专注于正交性,而不考虑便利性。

    自然希望有一个封装,让程序员在C代码中,尽可能地像Lua一样调用Lua。

    github上没搜到特别中意的,只好自己写一个,取名Lucy。设计目标:

    1) 隐藏虚拟栈——因此也隐藏基于虚拟栈的官方C API。

    2) 在C代码中,尽量用Lua的方式调用Lua代码。

    3) function和table在C代码中也该是第一类型,可以作为函数参数传递——其实是第2) 点的补充说明。

    在Lua这样的动态类型语言中,变量本身没有类型,被赋值后才有相应的类型。

    因此在Lucy中只需定义一个名为lucy_Data的结构体用以表示Lua变量:

    复制代码
    typedef struct {
        lucy_Type type_;
        lucy_Content cntnt_;
    } lucy_Data;
    复制代码

    lucy_Type是一个枚举类型,lucy_Content则是联合体。

    如此定义,则对lucy_Data作任何操作,编译期都没问题,而只会在运行期断言失败,算是对Lua变量的模拟。

    lucy_Content中有个类型lucy_Ref:

    复制代码
    typedef struct {
        lua_State *state_;
        int index_;
    } lucy_Ref;
    复制代码

    保存function, table这样的引用类型,在虚拟栈上的索引。于是它们就可以作为第一类型了。

    function传入参数,传出返回值的基础类型,都可以是lucy_Data的数组类型lucy_List。

    不难设计与实现剩下的接口。

    例如有以下Lua代码:

    复制代码
    function Loc(x, y)
        return function() return x, y end
    end
    
    function GetArea(loc)
        local x, y = loc()
        return x * y
    end
    复制代码

    给定x与y,通过调用GetArea函数来取得结果,通过Lucy封装后可以这么写(比如x与y都为5):

    复制代码
    lucy_File file = lucy_CreateFile();
    lucy_OpenFile(&file, "a.lua");
    lucy_Data Loc = lucy_GetData(&file, "Loc");
    lucy_Data five = lucy_Num(5);
    lucy_Data loc = lucy_Call(&Loc, 1, 2, &five, &five).datas_[0];
    lucy_Data GetArea = lucy_GetData(&file, "GetArea");
    lucy_Data area = lucy_Call(&GetArea, 1, 1, &loc).datas_[0];
    
    lucy_PrintData(&area);
    复制代码

    运行结果:

    代码已上传至: https://github.com/chncwang/Lucy

    已有的接口包括取变量,调用function,查询table元素,长度等。

     
    分类: Lua
  • 相关阅读:
    函数
    数组
    类的例题
    异常语句
    类的学习
    for的穷举、迭代
    for循环
    switch case
    反相器,扇入扇出
    T触发器,JK触发器的verilog实现
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2654068.html
Copyright © 2011-2022 走看看