C++读取sqlite的数据,导出lua表文件

参与制作的游戏内部有导出sqlite数据为lua表的步骤,引擎用的cocos2d,但是每次都要启动游戏exe

坐旁边的策划小哥想在手机远程操作公司电脑配置提交数值表,他表示手机没法启动游戏exe,但我没有我们的游戏的工程文件,抄不了前人的代码就自己动手简单实现了一下

新建控制台工程,自己编译集成了sqlite与lua的lib导入,略过不写

sqlitedbtest.cpp


#include "pch.h"
#include "include/sqlite3.h"
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <direct.h>

extern "C" {
	#include <lua.h>  
	#include <lualib.h>  
	#include <lauxlib.h>
}

using namespace std;
sqlite3 * pDB = NULL;
lua_State *L;
string result = "";
int pram_count = 0;
char *path;

bool getWorkPath();
int getInfo();
bool dirExists(const std::string& dirName_in);
int luaGetDirExists(lua_State *L);
int SelectInfo(lua_State *L);
int luaTest();
int setFunc();
int clearFunc(lua_State *L);
char* func(char * const str);
static void print_error(lua_State *L);

int main()
{
	getInfo();
	system("pause");
}



bool getWorkPath()
{
	//也可以将buffer作为输出参数
	if ((path = _getcwd(NULL, 0)) == NULL)
	{
		perror("getcwd error");
		return false;
	}
	else
	{
		printf("%s\n", path);
		return true;
	}
	return false;
}

string GbkToUtf8(const char *src_str)
{
	int len = MultiByteToWideChar(CP_ACP, 0, src_str, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_ACP, 0, src_str, -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
	string strTemp = str;
	if (wstr) delete[] wstr;
	if (str) delete[] str;
	return strTemp;
}

int getInfo()
{
	if (!getWorkPath())
	{
		printf("get path err");
		return 0;
	}

	string db_path(path);
	db_path = db_path + "\\data.db";
	printf("%s\n",db_path.c_str());
	db_path = GbkToUtf8(db_path.c_str());
	int nRes = sqlite3_open(db_path.c_str(), &pDB);
	//string db_path = path + "/data.db";
	//int nRes = sqlite3_open("E:/test/sqlitedbtest/sqlitedbtest/data.db", &pDB);
	if (nRes != SQLITE_OK)
	{
		cout << "Open database fail: " << sqlite3_errmsg(pDB);
		goto QUIT;
	}
	setFunc();
QUIT:
	sqlite3_close(pDB);
	pDB = NULL;
	return 0;
}

bool dirExists(const std::string& dirName_in)
{
	DWORD ftyp = GetFileAttributesA(dirName_in.c_str());
	if (ftyp == INVALID_FILE_ATTRIBUTES)
		return false;  //something is wrong with your path!  

	if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
		return true;   // this is a directory!  

	return false;    // this is not a directory!  
}

int luaGetDirExists(lua_State *L)
{
	int n = lua_gettop(L);
	string _path = lua_tostring(L, 1);
	bool ifExists = dirExists(_path);
	lua_pushboolean(L,ifExists);
	return 1;
}

static int UserResult(void *NotUsed, int argc, char **argv, char **azColName)
{
	string s = "{";
	string k, v;
	for (int i = 0; i < argc; i++)
	{
		if (argv[i] != NULL)
		{
			v = func(argv[i]);
		}
		else
		{
			v = "";
		}
		if (azColName[i] != NULL)
		{
			k = azColName[i];
		}
		else
		{
			k = "";
		}
		//将key,value转换为字符串表现
		s = s + "[\"" + k + "\"]" + "=\"" + v + "\"";
		
		if (i != argc - 1)
		{
			s += ",";
		}
		else
		{
			s = s + "},\n";
		}
		
		//cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL") << ", ";
	}
	result += s;
	pram_count++;
	return 0;
}

int SelectInfo(lua_State *L)
{
	int n = lua_gettop(L);
	string select = lua_tostring(L, 1);
	select += ";";

	char* cErrMsg;
	int res = sqlite3_exec(pDB, select.c_str(), UserResult, 0, &cErrMsg);

	if (res != SQLITE_OK)
	{
		cout << "select fail: " << cErrMsg << endl;
		cout << "check db'size and change the correct db" << endl;
		return false;
	}
	for (size_t i = 0; i < 2; i++)
	{
		result.pop_back();
	}
	result = "{" + result + "}";
	lua_pushstring(L, result.c_str());
	lua_pushnumber(L, pram_count);
	return 2;
}

int luaTest()
{
	/*

	L = luaL_newstate();
	lua_getglobal(L, "ruler");   //函数名为ruler
	lua_pcall(L, 0, 0, 0);          //用保护模式调用lua函数,入参个数为0、出参个数为0、无自定义错误处理

	//b、有参函数
	lua_getglobal(L, "add");     //函数名为add
	lua_pushnumber(L, 1);  //第一个入参
	lua_pushnumber(L, 2);  //第二个入参
	lua_pcall(L, 2, 1, 0); lua_getglobal(L, "ruler");   //函数名为ruler
	lua_pcall(L, 0, 0, 0);          //用保护模式调用lua函数,入参个数为0、出参个数为0、无自定义错误处理

	//b、有参函数
	lua_getglobal(L, "add");     //函数名为add
	lua_pushnumber(L, 1);  //第一个入参
	lua_pushnumber(L, 2);  //第二个入参
	lua_pcall(L, 2, 1, 0);
	*/

	//2、创建lua环境
	L = luaL_newstate();
	if (L == NULL)
	{
		cout << "Creat Lua State Error !" << endl;
		return 1;
	}
	//如需在终端输出打印信息,库是必须加载的,否则看不到lua的print信息
	luaL_openlibs(L);
	//3、加载lua脚本
	const string lua_path = "../sqlitedbtest/";
	const string file = "mylua.lua";
	string script = lua_path + file;
	int ret = luaL_dofile(L, script.c_str());
	if (ret)
	{
		cout << "Lua doFile Error !" << endl;
		return 1;
	}
	//4、调用脚本中已写好的函数
	  //a、无参函数
	lua_getglobal(L, "ruler");   //函数名为ruler
	lua_pcall(L, 0, 0, 0);          //用保护模式调用lua函数,入参个数为0、出参个数为0、无自定义错误处理

	//b、有参函数
	lua_getglobal(L, "add");     //函数名为add
	lua_pushnumber(L, 1);  //第一个入参
	lua_pushnumber(L, 2);  //第二个入参  
	lua_pcall(L, 2, 1, 0);          //函数有两个入参,一个出参,所以函数形式为add(a,b)
  //5、获得返回值,单回值情况下调用完成后lua会把结果放到栈顶,多返回值时,按照规则存放,具体查API
	if (lua_isnumber(L, -1))
	{
		cout << "the result is :" << lua_tonumber(L, -1) << endl;
	}
	//6、销毁lua环境
	lua_close(L);
	return 0;
}

int setFunc()
{
	L = lua_open();
	luaL_openlibs(L);
	//luaopen_base(L);

	/* 往lua中注册函数    
	lua_pushvalue(L, LUA_GLOBALSINDEX);
	lua_pushstring(L, "SelectInfo");
	lua_pushcfunction(L, SelectInfo,1);
	lua_rawset(L, -3);
	lua_pop(L, 1);
	*/

	lua_register(L, "luaGetDirExists", luaGetDirExists);
	lua_register(L, "SelectInfo", SelectInfo);
	lua_register(L, "clearFunc", clearFunc);
	const string file = "\\mylua.lua";
	string script = path + file;
	printf("%s\n", script.c_str());

	int ret = luaL_dofile(L, script.c_str());
	if (ret)
	{
		print_error(L);
		cout << "Lua doFile Error !" + ret << endl;
		return 1;
	}
	
	lua_close(L);
	return 0;
}

int clearFunc(lua_State *L)
{
	result = "";
	pram_count = 0;
	return 0;
}

//去掉行尾的'/r'
char *func(char * const str)
{
	int i, j;
	for (i = 0; str[i];) {
		if (str[i] == '\n' || str[i] == '\r' || str[i] == '\t' || str[i] == ' ') {
			for (j = i; str[j]; j++) {
				str[j] = str[j + 1];
			}
		}
		else i++;
	}
	return str;
}

static void print_error(lua_State *L)
{
	fprintf(stderr, "\nFATAL ERROR:%s\n\n", lua_tostring(L, -1));
}

然后在lua里制定数据格式,导出lua文件

入口文件mylua.lua,ddinfo里初始化了所有的表为空表,如dd.equip = {}这样的,写得有点乱将就看一下

require "ddinfo"
require "getDBInfo"

function getPath()
    -- print("this is some thing need to tell you !!!");
    local info = debug.getinfo(1, "S") -- 第二个参数 "S" 表示仅返回 source,short_src等字段, 其他还可以 "n", "f", "I", "L"等 返回不同的字段信息

	for k,v in pairs(info) do
	        print(k, ":", v)
	end

	local path = info.source

	path = string.sub(path, 2, -1) -- 去掉开头的"@"

	path = string.match(path, "^.*\\") -- 捕获最后一个 "/" 之前的部分 就是我们最终要的目录部分

	print("dir=", path)
	return path
end

function Split(str, delim)   
    -- Eliminate bad cases...   
    if str == "" or str == nil then
        return {}
    end       
    if string.find(str, delim) == nil then  
        return { str }  
    end  
    _,len = string.find(str, delim)
    if len <= 0 then
        return {str}
    end    

    local result = {}  
    local pat = "(.-)" .. delim .. "()"   
    local nb = 0  
    local lastPos   
    for part, pos in string.gfind(str, pat) do  
        nb = nb + 1  
        result[nb] = part   
        lastPos = pos   
    end  
    -- Handle the last field   
    result[nb + 1] = string.sub(str, lastPos)   
    return result   
end

function clearCfg()
	-- local pathStr = cc.FileUtils:getInstance():fullPathForFilename("data.lua")
	-- local relPathStr = string.gsub(pathStr, "data.lua","") 
	--将exe放到lua文件夹下
	local cfg = io.open(getPath().."cfg/cfg.lua","w+")
	io.close(cfg)
end

function makeLuaTableFile(tb,head,name,add)
	if tb == nil then
		return
	end
	if add == nil then
		add = false
	end

	local relPathStr = getPath()
	cclog("relPathStr:"..relPathStr)

    -- if not file_exists(relPathStr.."cfg.lua") then
    --     cclog("cfg not exists")
    -- else
    --     cclog("cfg exists")
    -- end
    if not luaGetDirExists(relPathStr.."cfg") then
        os.execute("mkdir \"" .. relPathStr.."/cfg" .. "\"")
    end

	local file = nil
	if add == true then
		file = io.open(relPathStr.."cfg/"..name..".lua","a+")
	else
		file = io.open(relPathStr.."cfg/"..name..".lua","w+")
	end
	cclog(relPathStr.."cfg/"..name..".lua")
	file:write(head.." = {}\n")

	outFile(file,head,tb)
	io.close(file)

	if add == false then
		local cfg = io.open(relPathStr.."cfg/cfg.lua","a+")
		cfg:write("require \"cfg/"..name.."\"\n")	
		io.close(cfg)
	end
end
function outFile(file,head,tb)
	for k,v in pairs(tb) do
		if type(v) == "table" then
			if type(k) == "number" then
				local line = head.."["..k.."] = {}\n"
				file:write(line)
				outFile(file,head.."["..k.."]",v)
			else
				local line = head.."['"..k.."'] = {}\n"
				file:write(line)
				outFile(file,head.."['"..k.."']",v)
			end
		elseif type(v) == "number" then
			if type(k) == "number" then
				local line = head.."["..k.."] = "..v.."\n"
				file:write(line)			
			else
				local line = head.."['"..k.."'] = "..v.."\n"
				file:write(line)			
			end
		else
			if string.byte(v,-1) == 13 then
				v = string.sub(v,1, string.len(v) - 1)			
			end
			if type(k) == "number" then
				local line = head.."["..k.."] = '"..v.."'\n"
				file:write(line)			
			else
				local line = head.."['"..k.."'] = '"..v.."'\n"
				file:write(line)			
			end
		end
	end
end

cclog = function(...)
    print(string.format(...))
end

function __G__TRACKBACK__(msg)
	cclog("----------------------------------------")
    cclog("LUA ERROR: " .. tostring(msg) .. "\n")
    cclog(debug.traceback())
    cclog("----------------------------------------")
end

data = {}
tb = {}

function data:getString(i,pram)
    return tb[i][pram]
end

function data:clear()
    clearFunc()
    tb = {}
end

function main()
    clearCfg()
    initTablesOK()
end

xpcall(main, __G__TRACKBACK__)

getDBInfo.lua

function initTablesOK()
    local str,count = SelectInfo("select * from tablename_in_db")
    --用loadstring获取用数据制成的表
    --loadstring 将字符串内容解读成一个方法,失败返回nil
    --C++中已经将数据库查询到的数据转换成表的形式返回成str
    local func = loadstring("return "..str)
    tb = func()
    for i=1,count do
        local id = tonumber(data:getString(i,"F0"))
        dd.cfgXXX[id] = {}
        dd.cfgXXX[id]["name"] = tonumber(data:getString(i,"F1"))         
    end
    makeLuaTableFile(dd.cfgXXX,"dd.cfgXXX","tablename_in_db")
    data:clear()
end

读取data.db的数据,最后导出的lua配置表文件在exe所在文件夹下的cfg文件夹中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值