zoukankan      html  css  js  c++  java
  • [转]使用 C 编写 Lua 模块

    Lua 作为一种小巧的语言,一般都是嵌入到 C/C++ 中作为扩展语言,但是也可以作为独立的脚本语言使用,并且可以使用 C/C++ 编写扩展模块。在参考资料 [1] 中有怎样用 C/C++ 编写模块的介绍,但是比较零散,也不是很详细,所以在这里整理一下。

    这里使用的 Lua 版本是 5.2.3,系统是 Debian 7。

    Hello, world!

    不废话,还是先看一下经典的 “Hello, world!” 例子。

    luahello.c
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
     
    static int l_hello(lua_State* l)
    {
        printf("Hello, world!
    ");
        return 0;
    }
     
    static const struct luaL_Reg hello_lib[] = {
        {"hello", l_hello},
        {NULL, NULL},
    };
     
    int luaopen_luahello(lua_State* l)
    {
        luaL_newlib(l, hello_lib);
        return 1;
    }

    这里用到的一个函数是

    void luaL_newlib (lua_State *L, const luaL_Reg *l);

    它其实是一个宏,被定义为

    (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))

    作用是先创建一个新的 table,再把指定的函数注册到这个 table 中。

    要注意的是,创建自定义模块的函数都需要以 “luaopen_” 作为函数名的前缀,这样在 require 中加载某个模块(例如这里的模块名叫 “luahello”)的时候,Lua 会去找相应的创建模块的函数(例如 luaopen_luahello),然后调用这个函数,获得对应的返回值,之后就可以被使用了。

    另外由于 require 的参数是一个字符串,如果我们写成 “require(‘a.b’)” 也是合法的,但是在 C 语言中无法定义 “luaopen_a.b” 这样一个函数。Lua 很智能地为我们做了转换,将 “.” 转换成 “_”。

    编译和执行

    先说一下静态加载的方法。

    查看 src/Makefile,可以发现 Lua 为我们预留了一些编译变量,例如 MYCFLAGS 和 MYLIBS 等。如果需要解析器能使用我们自己编写的模块,只需把我们的模块加到这些变量中。根据参考资料 [1] 的建议,还需要修改 luaL_openlibs(),把 luaopen_hello() 添加到 loadedlibs[] 这个数组中,让 Lua 解析器调用相应的函数后才能被调用。如果要把上面的模块编译到 Lua 解析器中,可以把 luahello.o 加入到MYOBJS 中:

    make posix MYOBJS=`pwd`/luahello.o -C /path/to/lua

    重新编译之后就能使用我们自定义的函数了。

    可见每增加一个模块就要重新编译一次 Lua 显然是不现实的,因此更好的方法是采用动态加载。

    Lua 默认只生成静态链接库 liblua.a,编译 Lua 解析器也是用的静态链接。但是 Lua 的实现中用到了一个全局变量,如果多次链接 liblua.a 会出问题(见参考资料 [2]),因此如果主程序和模块都分别链接了 liblua.a,接着主程序加载了模块运行会导致程序崩溃,需要使用选项 “-Wl,-E” 重新编译 Lua 解析器;为了能加载动态链接库,还需要打开相应的选项,在 Linux 下完整的编译命令为:

    make posix MYCFLAGS="-DLUA_USE_DLOPEN -Wl,-E" MYLIBS="-ldl"

    重新编译后应该就能正常加载运行脚本了。作为实验封装了一个 MySQL 的 Lua 客户端,放在 这里

    参考资料

  • 相关阅读:
    omnibus gitlab-ce安装
    Helm
    pod状态为Back-off
    我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
    云主机搭建Kubernetes 1.10集群
    Linux清除Windows密码
    Nginx负载均衡之健康检查
    MariaDB主从复制搭建
    Python基础
    Tomcat URL重写
  • 原文地址:https://www.cnblogs.com/freebird92/p/4686008.html
Copyright © 2011-2022 走看看