概述
近來研究Lua這個東西,官網爲http://www.lua.org/
主要的目的是通過lua來對短信發送過來的業務報文轉換爲業務系統支持的格式,設計的思想是Lua進行業務報文的轉換,報文的通訊採用c實現,因爲要通過C實現SGIP協議報文的封裝和到後臺業務的轉換。
C調用Lua函數
- 首先要進行Lua的初始化,這個主要是lua_open和luaL_openlibs函數
- 然後是解析並編譯lua的代碼,這個主要是luaL_dofile函數
- 解析好之後使用lua_getglobal指明要調用的lua函數
- 如果有lua函數的參數,通過使用lua_pushstring函數傳遞參數
- 最後調用lua_pcall進行lua函數的調用
- 調用完成之後採用lua_tonumber類函數可以獲取到函數的返回結果
Lua調用C函數
- 在Lua中調用C的函數,該函數必須進行註冊,這個通過lua_register這個函數來完成
- 在Lua中調用註冊的函數,會調用上面註冊的函數(類似於回調),所有的處理在這個函數裏面
- 這個函數裏面可以使用lua_tostring類函數來獲取函數的參數
- 如果有返回值,通過lua_pushnumber這個函數來返回。
參考的代碼
下面的這個代碼是用來將聯通的短信進行報文的轉換,同時對Lua註冊了一個SendSms函數用來可以在Lua中發送短信。
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#define cutil_log_error printf
#define cutil_log_debug printf
/**
* LuaSendSms
* 當Lua裏面調用SendSms函數時候會觸發該函數
*/
static int LuaSendSms(lua_State *L)
{
char *pszPhone = "";
char *pszMessage = "";
// 讀取並判讀參數
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "Incorrect argument number!");
lua_error(L);
}
if(!lua_isnumber(L, 1) || !lua_isstring(L, 2))
{
lua_pushstring(L, "Incorrect argument!");
lua_error(L);
}
pszPhone = lua_tostring(L, 1);
pszMessage = lua_tostring(L, 2);
// 發送消息 TODO
cutil_log_debug("Send Message %s to %s.\n", pszMessage, pszPhone);
// 返回結果
lua_pushnumber(L, 0);
// 只有一個返回結果
return 1;
}
/**
* LuaProcessSms
* 調用Lua裏面的LuaMain函數進行消息的處理
*/
static int LuaProcessSms(lua_State *L, char *pszPhone, char *pszMessage)
{
int nRet;
char *pszRetInfo;
cutil_log_debug("process phone %s message %s\n", pszPhone, pszMessage);
// 調用函數和參數
lua_getglobal(L, "LuaMain");
lua_pushstring(L, pszPhone);
lua_pushstring(L, pszMessage);
if(nRet = lua_pcall(L, 2, 2, 0))
{
cutil_log_error("lua_pcall error ret %d error '%s'. phone %s message %s\n",
nRet, lua_tostring(L, -1), pszPhone, pszMessage);
lua_settop(L, 0);
return -1;
}
// 判讀返回參數合法性
if(lua_gettop(L) != 2)
{
cutil_log_error("Incorrect return number. %d phone %s message %s\n",
lua_gettop(L), pszPhone, pszMessage);
lua_settop(L, 0);
return -1;
}
if(!lua_isnumber(L, 1) || !lua_isstring(L, 2))
{
cutil_log_error("Incorrect return. arg1 %s arg2 %s phone %s message %s\n",
lua_tostring(L, 1), lua_tostring(L, 2),
pszPhone, pszMessage);
lua_settop(L, 0);
return -1;
}
// 獲取並處理返回信息 TODO
nRet = lua_tonumber(L, 1);
pszRetInfo = strdup(lua_tostring(L, 2));
lua_settop(L, 0);
cutil_log_debug("Ret %d Info %s\n", nRet, pszRetInfo);
if(nRet != 0)
{
cutil_log_error("process info error phone %s message %s ret %d info %s\n",
pszPhone, pszMessage, nRet, pszRetInfo);
free(pszRetInfo);
return -1;
}
free(pszRetInfo);
return 0;
}
/**
* LuaInit
* 初始化Lua庫,並註冊一個SendSms函數
*/
static lua_State *LuaInit()
{
lua_State *L = lua_open();
if(L == NULL)
{
cutil_log_error("Init the lua library error\n");
return NULL;
}
luaL_openlibs(L);
/* register our function */
lua_register(L, "SendSms", LuaSendSms);
return L;
}
int main()
{
int i;
lua_State *L;
L = LuaInit();
if (luaL_dofile(L, "sms.lua"))
error(L, "cannot run configuration file: %s",
lua_tostring(L, -1));
for(i = 0; i < 1; i ++)
LuaProcessSms(L, "13988227711", "測試消息");
lua_close(L);
}
下面是參考的Lua程序
-- 函數名稱必須爲LuaMain
-- 函數裏面可以調用SendSms進行消息發送,第一個參數是手機號碼,第二個參數是內容
-- 函數的參數有兩個phone是手機號碼 message是接收到的短信內容
-- 返回參數有兩個 第一個是返回值0表示成功,其他失敗,第二個是要求發送的內容
function LuaMain(phone, message)
print("phone ", phone, "message", message)
SendSms('13988221133', '你好')
return 0,'KZCZ函數的參數有兩個phone是手機號碼 message是接收到的短信內容'
end
-- 這個裏面可以有全局的代碼,不過建議不要編寫
-- 全局的代碼會在LuaMain函數之前運行