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

以上。

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

相关推荐
什么都想学的阿超7 小时前
【Redis系列 03】掌握Redis编程艺术:事务、管道与Lua脚本完全指南
redis·junit·lua
编程乐学(Arfan开发工程师)11 小时前
42、响应处理-【源码分析】-浏览器与PostMan内容协商完全适配
java·spring boot·后端·测试工具·lua·postman
啾啾Fun14 小时前
【Java微服务组件】分布式协调P4-一文打通Redisson:从API实战到分布式锁核心源码剖析
java·redis·分布式·微服务·lua·redisson
多多*16 小时前
LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考
linux·开发语言·redis·python·bootstrap·lua
修电脑的猫1 天前
带有输入的CDS和程序调用
开发语言·lua
代码丰2 天前
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
java·分布式·lua
wcjwdq2 天前
Lua和JS的继承原理
javascript·lua·脚本继承
哈哈哈哈哈哈哈哈哈...........2 天前
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
tcp/ip·nginx·lua
程序猿多布5 天前
Unity使用Lua框架和C#框架开发游戏的区别
unity·c#·lua
chiou7225 天前
为 Ubuntu 安装的软件创建桌面图标
linux·ubuntu·lua