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

以上。

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

相关推荐
玩转C语言和数据结构1 天前
Lua下载和安装教程(附安装包)
lua·lua下载·lua安装教程·lua下载和安装教程·lua安装包
Arva .1 天前
HTTP Client
网络协议·http·lua
爱吃小胖橘2 天前
Lua语法(2)
开发语言·unity·lua
ellis19703 天前
LuaC API知识点汇总
unity·lua
爱吃小胖橘6 天前
Lua语法
开发语言·unity·lua
东方芷兰6 天前
JavaWeb 课堂笔记 —— 20 SpringBootWeb案例 配置文件
java·开发语言·笔记·算法·log4j·intellij-idea·lua
1nullptr6 天前
Lua上值与闭包
开发语言·lua
半夏知半秋8 天前
skynet-socket.lua源码分析
服务器·开发语言·学习·架构·lua
夜猫逐梦11 天前
【lua】luajit 命令行使用指南
开发语言·lua
利来利往11 天前
【奇怪的bug】lua的nil不报错
开发语言·bug·lua