lua移植及使用
编译环境:Ubuntu16.04 64位
交叉编译工具:arm-hisiv500-linux-gcc
1. 项目背景
使用lua脚本,读取key对应的值,用作设备的默认配置。
2. lua开源版本选择
使用lua-5.4.6.tar.gz点击下载,早期使用lua-5.0.2.tar.gz,在部分平台上存在浮点运算错误的问题,放弃。
3. 封装代码
3.1 源码简介
源码的目录结构比较简单,只有一个src目录,Makefile略作修改即可,或者根据自己项目做简化。
lua.hpp文件内容如下,外部调用主要用到就是这三个头文件,在编译C++工程时注意extern “C”:
// lua.hpp
// Lua header files for C++
// <<extern "C">> not supplied automatically because Lua also compiles as C++
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
3.2 封装类
3.2.1 头文件
#ifndef __LUA_CONFIG_H__
#define __LUA_CONFIG_H__
#include <string>
#include <pthread.h>
struct lua_State;
typedef struct lua_State lua_State;
class LuaConfig
{
public:
static int Initialize(void);
static int Invalidate(void);
static LuaConfig* instance(void);
private:
static LuaConfig* s_instance;
LuaConfig(void);
virtual ~LuaConfig(void);
LuaConfig(LuaConfig &); // 拷贝构造函数,禁止拷贝
public:
int Init(const char * filename);//要解析的lua文件,可以按照lua语法包含其他lua
void unInit();
///< 根据传入的键值返回相应的字符串
///< key为要访问的键值
///< defaultValue为默认值,当访问的键值不存在时返回
std::string getString(const char * key, const char * defaultValue="");
///< 根据传入的键值返回相应的double值,与getString类似
///< key为要访问的键值
///< defaultValue为默认值,当访问的键值不存在时返回
double getNumber(const char * key, double defaultValue = 0);
private:
int TravelTable(const char * key);
private:
lua_State *m_luastate;
pthread_mutex_t m_Mutex;
};
#endif //__LUA_CONFIG_H__
3.2.2 类的实现
#include "LuaConfig.h"
#include <string.h>
#include <stdlib.h>
extern "C"
{
#include "lua/lua.h"
#include "lua/lauxlib.h"
#include "lua/lualib.h"
};
int LuaConfig::Initialize(void)
{
if(s_instance != NULL)
return -1;
s_instance = new LuaConfig;
return 0;
}
int LuaConfig::Invalidate(void)
{
if(s_instance == NULL)
return 0;
delete s_instance;
return 0;
}
LuaConfig* LuaConfig::instance(void)
{
return s_instance;
}
LuaConfig* LuaConfig::s_instance = NULL;
LuaConfig::LuaConfig()
{
m_luastate = NULL;
pthread_mutex_init(&m_Mutex, NULL);
}
LuaConfig::~LuaConfig()
{
unInit();
pthread_mutex_destroy(&m_Mutex);
}
int LuaConfig::Init(const char * filename)
{
if (m_luastate != NULL)
return -1;
if (filename == NULL)
return -2;
#if 0 // 5.0.2的封装
m_luastate = lua_open();
if (m_luastate == NULL)
return -3;
luaopen_base(m_luastate);
luaopen_table(m_luastate);
luaopen_io(m_luastate);
luaopen_string(m_luastate);
luaopen_math(m_luastate);
luaopen_debug(m_luastate);
//luaopen_lfs(m_luastate);
//luaopen_bitlib(m_luastate);
if (lua_dofile(m_luastate, filename) != 0)
return -4;
#else//5.4.6
m_luastate = luaL_newstate();
if (m_luastate == NULL)
return -3;
luaL_openlibs(m_luastate);
if (luaL_dofile(m_luastate, filename) != 0)
return -4;
#endif
return 0;
}
void LuaConfig::unInit()
{
if (m_luastate != NULL)
{
lua_close(m_luastate);
m_luastate = NULL;
}
return;
}
std::string LuaConfig::getString(const char * key, const char * defaultValue)
{
pthread_mutex_lock(&m_Mutex);
int nTop = lua_gettop(m_luastate);
int status = TravelTable(key);
std::string ret = defaultValue;
if( (status == 0) && (lua_isstring(m_luastate, -1)))
{
ret = lua_tostring(m_luastate, -1);
}
lua_settop(m_luastate, nTop);
pthread_mutex_unlock(&m_Mutex);
return ret;
}
double LuaConfig::getNumber(const char * key, double defaultValue)
{
pthread_mutex_lock(&m_Mutex);
int nTop = lua_gettop(m_luastate);
int status = TravelTable(key);
double ret = defaultValue;
if( (status == 0) && (lua_isnumber(m_luastate, -1)))
{
ret = lua_tonumber(m_luastate, -1);
}
lua_settop(m_luastate, nTop);
pthread_mutex_unlock(&m_Mutex);
return ret;
}
int LuaConfig::TravelTable(const char * key)
{
// 创建匿名函数
int len = strlen(key) + 16;
char* szFunc = (char*)malloc(len);
memset(szFunc, 0, len);
sprintf(szFunc, "return %s", key);
int status = luaL_loadbuffer(m_luastate, szFunc, strlen(szFunc), "table_travel");
if(status == 0)
{
status = lua_pcall(m_luastate, 0, LUA_MULTRET, 0);
}
free(szFunc);
return status;
}
3.3.3 sample代码
LuaConfig::Initialize();
LuaConfig* pCfg = LuaConfig::instance();
pCfg->Init("./test.lua");
int testA = (int)LuaConfig::instance()->getNumber("testA", 0);
std::string testB = LuaConfig::instance()->getString("testB", "123456");
if (pCfg != NULL)
{
pCfg->unInit();
LuaConfig::Invalidate();
}
以上。
转载请注明出处,如有错漏之处,敬请指正。