前言
本文讲述sqlite3数据库的交叉编译方法以及如何将编译后的文件移植到开发板平台上。
特点
sqlite3作为一款高可靠性且小巧玲珑的数据库工具,遵守ACID的关联式数据库管理系统,它的跨平台特性使得它十分适合在嵌入式领域使用。它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。
开发环境
windows10
ubuntu16.04
源码获取
Sqlite官网提供了源码下载,下载链接点击,进入下载页面,发现sqlite提供了多个版本,由于我们需要嵌入式移植,应当选择源码进行下载, 点击sqlite-autoconf-3330000.tar.gz进行下载保存即可。
源码编译
1.将下载好的源码压缩包导入到ubuntu。如图所示。
2.解压压缩包
tar -zxvf sqlite-autoconf-3330000.tar.gz
解压完成后会在当前目录下生成同名的文件夹sqlite-autoconf-3330000,进入文件夹可以看到有如下内容。
3.在进入到sqlite-autoconf-3330000文件夹后,执行
./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf --prefix=/home/lyk/sqlite-autoconf-3330000/myfile
其中
CC:指定嵌入式平台为arm-linux-gnueabihf-gcc,需要根据你板子的交叉编译工具进行配置。
–host: 指定交叉编译工具,一般为arm-linux、arm-linux-gnueabihf、arm-none-linux-gnueabi等,具体要和板子用的交叉编译工具对应。
–prefix: 指定安装目录,编译后的文件会全部放在安装目录中,必须是绝对路径。
如果不配置 --prefix 选项,安装后:可执行文件默认放在/usr /local/bin,库文件默认放在/usr/local/lib,
配置文件默认放在/usr/local/etc,其它的资源文件放在/usr /local/share。
需要注意的是每一项配置的等号两边不能有空格。
运行完该命令后会发现文件夹新增了一个Makefile的文件。如图所示。
4.执行
make
此过程需要等待一定的时间。
5.执行
make命令执行完毕后执行make install命令
执行完毕后可以在当前目录下生成了一个myfile的文件夹,该文件夹就放置了交叉编译后的可执行文件和头文件以及相应的库文件。如图所示。
交叉编译后的文件移植到开发板
1.文件瘦身
交叉编译完成后的文件一般比较大,因为里面包含了大量的调试信息,剔除调试信息的工具为
arm-linux-strip
例如我们可以进入库文件目录来对比瘦身前后的静态库文件libsqlite3.a大小。
瘦身前
瘦身后
通过这样的文件瘦身,可以大大节省开发板的存储空间。
2.接着将myfile/bin/sqlite3拷到开发板的/usr/bin目录下;将myfile/lib/下的所有库拷贝到开发板的/usr/lib/下,至此sqlie3的嵌入式移植工作完成。
注意:cp –arf libsqlite3.so.0 libsqlite3.so.0.8.6 /usr/lib 加上arf的目的是将源库拷贝,千万别只拷贝个链接,那么就悲剧了。。。
相关API函数
int sqlite3_open(char *path, sqlite3 **db);
功能:打开sqlite数据库
函数参数:
path:数据库文件路径
db: 指向sqlite句柄的指针
返回值:成功返回0,失败返回错误码(非零值)
int sqlite3_close(sqlite3 *db);
功能:关闭sqlite数据库
函数参数:
db: 指向sqlite句柄的指针
返回值:
成功返回0,失败返回错误码
const char *sqlite3_errmg(sqlite3 *db);
函数参数:
db: 指向sqlite句柄的指针
返回值:
返回错误信息
回调函数的定义:
typedef int (*sqlite3_callback)(void *para, int f_num, char **f_value, char **f_name);
功能:每找到一条记录自动执行一次回调函数
函数参数:
para:传递给回调函数的参数
f_num:记录中包含的字段数目
f_value:包含每个字段值的指针数组
f_name:包含每个字段名称的指针数组
返回值:
成功返回0,失败返回-1
范例:
int callback(void *para, int f_num, char **f_value, char **f_name)
{
int i;
printf("进入回调函数...\n");
for (i=0; i<f_num; i++)
{
printf("name:%s value:%s\n", f_name[i], f_value[i];
}
return 0;
}
int sqlite3_exec(sqlite3 *db, const char *sql, sqlite3_callback callback, void *, char **errmsg);
功能:执行SQL操作
函数参数:
db:数据库句柄
sql:SQL语句
callback:回调函数
errmsg:错误信息指针的地址
返回值:
成功返回0,失败返回错误码
范例:
sqlite3 *db;
char *errmsg;
if (sqlite3_exec(db, “select * from table”, callback, NULL, &errmsg) != SQLITE_OK)
{
printf(“error : %s\n”, errmsg);
exit(-1);
}
不使用回调函数执行SQL语句
int sqlite3_get_table(sqlite3 *db, const char *sql, char ***resultp, int*nrow, int *ncolumn, char **errmsg);
函数功能:执行SQL操作
函数参数:
db:数据库句柄
sql:SQL语句
resultp:用来指向sql执行结果的指针
nrow:满足条件的记录的数目
ncolumn:每条记录包含的字段数目
errmsg:错误信息指针的地址
返回值:
成功返回0,失败返回错误码
范例:
sqlite3 *db;
char *errmsg,**resultp;
int nrow, ncolumn, i, j, index;
if (sqlite3_exec(db, “select * from table”, &resultp, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
{
printf(“error : %s\n”, errmsg);
exit(-1);
}
index = ncolumn; // 第一条记录的第一个字段的下标
for (i=0; i<nrow; i++)
{
for (j=0; j<ncolumn; j++)
{
printf(“%s : %s\n”, resultp[j], resultp[index++]);
}
}
测试用例
#include <stdio.h>
#include "sqlite3.h" //对数据库接口进行声明 (必须要安装过数据库才能声明)
//操作的句柄
sqlite3 *fd=NULL;
int flag = 0;
//插入数据
int insert_data()
{
printf("请输入车辆的id 类型为 text\n");
char data[50] = {
0};
scanf("%s", data);
printf("请输入车辆的licence 类型为 text\n");
char data2[50] = {
0};
scanf("%s", data2)