使用Lua来操作Sqlite3数据库的过程,相比直接在C/C++下操作,简单得多。在嵌入式开发过程中,使用Sqlite3来管理系统中的大量数据,是一种非常成熟的做法;将Lua 和Sqlite3结合起来的开源技术Lua Sqlite3,就显得非常适合快速开发。
这篇文章就是根据在项目开发过程中,提炼出来的实际经验总结。主要涉及到的技术知识背景有:
1、Lua
2、Sqlite3
3、Lua Sqlite3
前面两点,网络资源非常丰富。第3点,网上的资源相比较少,主要就是官网的文档。
本篇博客主要内容有:
1、C/C++如何给Lua 函数传递参数?
2、Lua如何给C/C++返回多个值?
3、C/C++如何通过Lua 提供的接口访问Sqlite3 数据库?
下面详细讲解:
一、C/C++如何给Lua传递参数(传递多个参数)
1、首先我们写一个lua脚本,脚本中提供了一个lua函数。保存为test.lua:
function set_data(...)
local args = {...}
for i=1,#args do
print(args[i])
end
end
2、使用C++写一个测试程序,代码如下:
#include "lua.hpp"
#include
using namespace::std;
lua_State* g_L = NULL;
bool initlua()
{
g_L = luaL_newstate();//创建Lua栈
lua_checkstack(g_L,60);//修改Lua栈大小为60,防止在C和Lua之间传递大数据时,崩溃
luaL_openlibs(g_L);//运行Lua虚拟机
int ret;
if(ret=luaL_loadfile(g_L,"test.lua"))//装载lua脚本
{
cout<<"load test.lua fail."<
编译上面的CPP文件时,须链接lua的库 -llua -ldl
运行结果如下:
# ./lua-c-example
load test.lua ok
run test.lua ok
11
22
33
44
55
66
77
88
99
100
二、Lua函数如何给C/C++返回多个值
1、lua脚本内容如下,保存为test.lua:
local array = {1,2,4,5,6,7,8,9,10}
function get_data()
print("get_data")
return array
end
2、C++调用Lua函数,获取多个返回值的测试程序代码:
#include "lua.hpp"
#include
using namespace::std;
lua_State* g_L = NULL;
bool initlua()
{
g_L = luaL_newstate();
lua_checkstack(g_L,60);
luaL_openlibs(g_L);
int ret;
if(ret=luaL_loadfile(g_L,"test.lua"))
{
cout<<"load test.lua fail."<nil 入栈作为初始 key
if(lua_isnil(g_L, index))//栈顶内容为空
{
return ;
}
while(lua_next(g_L, index))//循环遍历栈中内容
{
cout<
运行结果如下:
# ./lua-c-example
load test.lua ok
run test.lua ok
get_data
1 2 4 5 6 7 8 9 10
三、C/C++通过Lua 提供的接口访问Sqlite3 数据库
结合一、二的讲解,应该很容易从C/C++端,通过lua提供的函数接口,访问sqlite3数据库。
1、Lua创建数据库和表的脚本如下:
local sqlite3 = require("lsqlite3") --加载 Lua Sqlite3 库
local mydb = sqlite3.open("test.db") --打开/或者创建test.db数据库
mydb:exec[[
CREATE TABLE main (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
year INTEGER,
month INTEGER,
day INTEGER,
hour INTEGER,
minite INTEGER,
second INTEGER);]]
2、数据插入操作,使用lua sqlite3的statement语句,以提高插入大量数据时的效率:
main_stmt = mydb:prepare[[
INSERT INTO main VALUES (
?, ?, ?, ?, ?, ?, ?);
]] --7 values 申明一个插入操作的statement
如下Lua函数为提供给C的数据库插入接口函数:
function insert_main(...)
local args = {...}
main_stmt:bind_values(nil,args[1],args[2],args[3],args[4],args[5],args[6])
main_stmt:step()
main_stmt:reset()
return 9
end --提供一个供C/C++调用的Lua函数 insert_main。此函数为数据插入接口。
3、数据查询操作,使用lua sqlite3的statement语句,以提高频繁查询时的效率:
select_stmt_main = mydb:prepare("SELECT * FROM main;")
如下Lua函数为提供给C的数据库查询接口函数:
function select_main()
local stepret = select_stmt_main:step()
if stepret == sqlite3.ROW then
local ret = select_stmt_main:get_values() --返回的是一个lua array
return ret
else
select_stmt_main:reset() --重置statement,以便下一次从表头开始查询
return nil
end
end
以上操作Sqlite3数据库的Lua脚本保存到一个文件db.lua中。结合前面的一、二提供的测试代码,很容易就达到了我们的目的——C/C++通过Lua 提供的接口访问Sqlite3 数据库。