要想 lua 中調(diào)用 c 函數(shù),c 文件如何修改?

2018-03-14 11:20 更新

背景:

    想要像 cjson,gd,libinjection 一樣,代碼是用 c 實(shí)現(xiàn)的,卻在 openresty 的 lua 模塊中被調(diào)用。

    ?下面以添加 ssdeep.so 為例,其中有 fuzzy_hash_buf 和 fuzzy_compare 兩個(gè)接口函數(shù)。

    lua 版本為 5.1.4,openresty 版本為 1.9.7.1?

??實(shí)踐:

1.添加頭文件,如下:?

//#include <lua.hpp>

#include <lauxlib.h>

//#include <lualib.h>

某些資料中顯示要添加三個(gè)頭,不過編譯時(shí)顯示lua.hpp找不到

我添加的ssdeep只需要lauxlib.h即可?


2.修改接口函數(shù)

原有fuzzy_hash_buf函數(shù)如下 :?

?char* fuzzy_hash_buf(const unsigned char *buf, uint32_t buf_len)
{
     ......
     return result;?
}?

現(xiàn)改為

int fuzzy_hash_buf_m(lua_State* L) {  //前期加上了extern "C",但是會(huì)報(bào)錯(cuò)
    const unsigned char *buf = (const unsigned char *)lua_tostring(L, 1);
    uint32_t buf_len = (uint32_t)lua_tonumber(L, 2); 
    char   result[FUZZY_MAX_RESULT];
?    .......
    lua_pushstring(L, result); //返回result值
  ?  return 1; //返回結(jié)果的數(shù)量
}?

注解:

所有注冊到 Lua 中的接口函數(shù)都具有相同的原型,該原型就是定義在 lua.h 中的 lua_CFunction:

?typedef int (*lua_CFunction) (lua_State *L);

接口函數(shù)返回值表示返回結(jié)果的數(shù)量

返回值通過 lua_pushstring 或者 lua_pushnumber 注入 L 中?


3.?接口函數(shù)列表

static LuaL_reg libs[] = { //開始為LuaL_Reg會(huì)報(bào)錯(cuò),原因是lua版本的問題
?    {"fuzzy_hash_buf", fuzzy_hash_buf},  
    {NULL, NULL} 
 
}?

?4.主函數(shù)

?int luaopen_ssdeep(lua_State* L)  
{  
    const char* libName = "ssdeep";    
    luaL_register(L, libName, libs);   
    return 1; 
}

?luaL_register 根據(jù)給定的名稱 ("ssdeep") 創(chuàng)建(或復(fù)用)一個(gè) table,并用數(shù)組 libs 中的信息填充這個(gè) table。在 LuaL_register 返回時(shí),會(huì)將這個(gè) table 留在棧中。最后返回1,表示將這個(gè) table 返回給 lua。


5.編譯及調(diào)用

    C 模塊完成后,必須將其鏈接到解釋器。如果 Lua 解釋器支持動(dòng)態(tài)鏈接的話,那么最簡便的方法就是使用動(dòng)態(tài)鏈接機(jī)制。在這種情況中,必須將 C 代碼編譯成動(dòng)態(tài)鏈接庫,并將這個(gè)庫放入 C 路徑(LUA_CPATH)中。然后便可以用 require 從 Lua 中加載這個(gè)模塊: require  "ssdeep" 會(huì)將動(dòng)態(tài)庫 ssdeep 鏈接到 Lua,并會(huì)尋找 luaopen_ssdeep 函數(shù),將其注冊為一個(gè) Lua 函數(shù),然后調(diào)用它以打開模塊。

    如果解釋器不支持動(dòng)態(tài)鏈接,那么就必須用新的模塊來重新編譯 Lua。此外,還需要以某種方式來告訴解釋器,它應(yīng)在打開一個(gè)新狀態(tài)的同時(shí)打開這個(gè)模塊。最簡單的做法是,將 luaopen_ssdeep 加到 luaL_openlibs 會(huì)打開的標(biāo)準(zhǔn)庫列表中,這個(gè)列表在文件 linit.c中。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)