• lua 加载C动态库


    今天翻看luasocket的C源码,也翻看了很多BSD Socket的资料,算是重新复习了一下BSD Socket. 在ubuntu上面使用安装使用luasocket,

    我安装的是lua5.1,不要使用apt安装luasocket && luasocket-dev. 如果采用这种方式安装,测试luasocket是不能使用的.我们应该安装库,

    安装liblua5.1-socket.这样才可以.

     

    原因是,luasocket在调用的时候是lua加载C的动态库. 这个可以从luasocket的makefile看的出来.

     1 all: $(SOCKET_SO) $(MIME_SO)
     2 
     3 $(SOCKET_SO): $(SOCKET_OBJS)
     4         $(LD) $(LDFLAGS) -o $@ $(SOCKET_OBJS)
     5 
     6 $(MIME_SO): $(MIME_OBJS)
     7         $(LD) $(LDFLAGS) -o $@ $(MIME_OBJS)
     8 
     9 $(UNIX_SO): $(UNIX_OBJS)
    10         $(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS)

    另外,也可以从config文件中找出:

    1 #------
    2 # Output file names
    3 #
    4 EXT=so
    5 SOCKET_V=2.0.2
    6 MIME_V=1.0.2
    7 SOCKET_SO=socket.$(EXT).$(SOCKET_V)
    8 MIME_SO=mime.$(EXT).$(MIME_V)
    9 UNIX_SO=unix.$(EXT)

    至于socket模块,按照config中的配置,编译后应该会生成一个socket.so.2.0.2的动态库.如果不想自己编译的话,也可以到网上去下载,编译

    完整的库可以搜索liblua5.1-socket.so.2.0.2.(应该是这个.)

     

    至于为什么会说到,lua加载C动态库这个问题,是因为我看到luasocket中socket.lua文件中的一句代码不明白:

    1 local socket = require("socket.core") // socket.core?

    如果不是加载一个模块的话,那么就是加载库,但是我在源码中没有找到这个库,再说,看到这个库的名字不感觉有点奇怪吗?

    不过,可以看看源码中的这段代码:

    1 /*-------------------------------------------------------------------------*\
    2 * Initializes all library modules.
    3 \*-------------------------------------------------------------------------*/
    4 LUASOCKET_API int luaopen_socket_core(lua_State *L) {
    5     int i;
    6     base_open(L);
    7     for (i = 0; mod[i].name; i++) mod[i].func(L);
    8     return 1;
    9 }

     base_open(lua_State *L)的函数源码如下:

     1 static int base_open(lua_State *L) {
     2     if (socket_open()) {
     3         /* export functions (and leave namespace table on top of stack) */
     4         luaL_openlib(L, "socket", func, 0);
     5 #ifdef LUASOCKET_DEBUG
     6         lua_pushstring(L, "_DEBUG");
     7         lua_pushboolean(L, 1);
     8         lua_rawset(L, -3);
     9 #endif
    10         /* make version string available to scripts */
    11         lua_pushstring(L, "_VERSION");
    12         lua_pushstring(L, LUASOCKET_VERSION);
    13         lua_rawset(L, -3);
    14         return 1;
    15     } else {
    16         lua_pushstring(L, "unable to initialize library");
    17         lua_error(L);
    18         return 0;
    19     }
    20 }

     其中,需要注意的是luaL_openlib函数的功能(ps:注意,不是luaL_openlibs函数,在lua官网上面可能找不到该函数的API解释.)

     

    另外,lua官网有文档说明,如何注册C库.详细的文档请去参考:http://www.lua.org/pil/26.2.html

    1 When you extend Lua with C functions, it is a good idea to design your code as a C library, even when you want to register only one C function: 
    Sooner or later (usually sooner) you will need other functions. As usual, the auxiliary library offers a helper function for this job. The luaL_openlib
    function receives a list of C functions and their respective names and registers all of them inside a table with the library name.

    现在已经弄明白在使用C扩展lua的时候,应该将我们的代码设计成为C库.

    另外,我这里有一个简单的实例程序:

     1 #include <stdio.h>
     2 #include "./src/lua.h"
     3 #include "./src/lualib.h"
     4 #include "./src/lauxlib.h"
     5 
     6 static int add(lua_State *L)
     7 {
     8 int a,b,c;
     9 a = lua_tonumber(L,1);
    10 b = lua_tonumber(L,2);
    11 c = a+b;
    12 lua_pushnumber(L,c);
    13 printf("test hello!!!\r\n");
    14 return 1;
    15 }
    16 static const struct luaL_Reg lib[] =
    17 {
    18 {"testadd",add},
    19 {NULL,NULL}
    20 };
    21 int luaopen_testlib_core(lua_State *L)  // 注意这里的函数写法
    22 {
    23 //luaL_register(L,"testlib",lib);   // 1
    24 luaL_openlib(L,"testlib",lib,0);    // 2
    25 return 1;
    26 }
    27 
    28 ~            

     下面给出一个lua脚本:

    1 #!/usr/bin/env lua
    2 require("testlib.core")  // 注意这里的调用,和上面的函数写法是相关联的
    3 c = testlib.testadd(15,25)
    4 print("The result is ",c);
    5 ~                          

     到这里就很明白了,如果我在上面的C源码中使用的是luaopen_testlib(lua_State *L),那么在下面的lua脚本中直接require("testlib")就可以了.

     但是如果是像我上面的这种命名方式,那么就需要像我这么做.而luasocket中出现的require("socket.core"),就是这么出现的.

     

     

     

     

     

     

     

     

     
  • 相关阅读:
    JS・TextArea 字符串长度限制
    JavaScript面试题目集锦
    IE内存泄露分析
    JS动态添加样式和脚本
    取消锚(<a/>)点击后页面跳转的几种方法
    JS代码片段整理
    IE缓存问题的解决方法
    字符串与数字 转换
    如何安装和配置Cassandra
    字类和超类的转化问题
  • 原文地址:https://www.cnblogs.com/respawn/p/2781786.html
Copyright © 2020-2023  润新知