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