lua移植及使用

编译环境:Ubuntu16.04 64位

交叉编译工具:arm-hisiv500-linux-gcc

文章目录

  • [1. 项目背景](#1. 项目背景)
  • [2. lua开源版本选择](#2. lua开源版本选择)
  • [3. 封装代码](#3. 封装代码)
    • [3.1 源码简介](#3.1 源码简介)
    • [3.2 封装类](#3.2 封装类)
      • [3.2.1 头文件](#3.2.1 头文件)
      • [3.2.2 类的实现](#3.2.2 类的实现)
      • [3.3.3 sample代码](#3.3.3 sample代码)

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();
}

以上。

转载请注明出处,如有错漏之处,敬请指正。

相关推荐
慢慢沉1 天前
Lua(数据库访问)
开发语言·数据库·lua
慢慢沉1 天前
Lua协同程序(coroutine)
lua
慢慢沉2 天前
Lua元表(Metatable)
lua
慢慢沉3 天前
Lua(字符串)
开发语言·lua
慢慢沉3 天前
Lua(数组)
开发语言·lua
慢慢沉3 天前
Lua(迭代器)
开发语言·lua
慢慢沉3 天前
Lua基本语法
开发语言·lua
Feng.Lee3 天前
接口测试Postman工具高级使用技巧
功能测试·测试工具·lua·postman·可用性测试
三翼鸟数字化技术团队4 天前
鸿蒙平台运行Lua脚本
lua·harmonyos