今天翻看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"),就是这么出现的.