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

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM