SQLite下载、编译和使用-3

\color{green}{文章付费是对Copyleft精神的亵渎,阅后点赞、关注才是对作者最大的奖赏!---Devil}


May you do good and not evil.
May you find forgiveness for yourself and forgive others.
May you share freely, never taking more than you give.

SQLite源码下载

 SQLite代码完全开源,可直接访问SQLite官网提供的下载地址SQLite源码下载进行源码的下载。其下载源码有多种类型,在这里推荐两种类型(支持点我下载,最新版本3.28.0,更新后可能失效):

  1. amalgamation合并型Src:该方法下载到的源码文件中只有sqlite3.c、sqlite3.h、sqlite3ext.h、shell.c四个文件,非常方便在自己的工程代码中集成该源码,集成方法继续往后阅读。
  2. arch源码树型Src:该方法下载到的源码是Arch版本的,不同功能的文件被整理到不同文件夹下,更符合我们的阅读习惯,在学习SQLite源码时,更建议使用该类型的下载方法下载源码。

我们的事例采用虚拟机上安装centos7的linux环境编译和调试,作为一个程序猿,使用Linux的重要性参考大学四年一文,如果你志向与windows\IOS开发,请忽略并继续。如何在虚拟机上安装Centos7网上很多方法,此处不做介绍,有问题可留言,力所能及处必解答。
代码上传CentOS方法可参考:

  1. 使用secureCRT软件ssh登录centos7服务器(非常通用的工具,使用方法不再赘述),使用rz命令上传windows本地tar文件;
  2. 使用VMware workstation的ShareFileFolder功能。
    2.1 具体步骤为 【打开VMware】- 【虚拟机(M)】- 【设置】,打开虚拟机设置页面,选择【选项】-【共享文件夹】,添加文件夹映射。
    2.2 共享的文件夹一般被挂载到centos系统的/mnt/hgfs目录下,将安装包放置到该共享文件夹下,linux系统上直接访问即可

SQLite源码编译

一、使用arch型源码编译

 下载到的源码解压并执行configure得到该平台下的Makefile后,直接make即可

[root@localhost sqlite3] tar -zxvf sqlite-src-3280000.zip
--我这边解压并重命名等处理后,源码位于sqlite-src-arch
[root@localhost sqlite3]# ls
sqliteOne sqlite-src-arch
[root@localhost sqlite3]# cd sqlite-src-arch/
[root@localhost sqlite-src-arch]# ./configure
[root@localhost sqlite-src-arch]# make

make后在该目录下生成sqlite3.c、sqlite3.h、sqlite3ext.h、shell.c四个源文件和1个sqlite可执行程序。

二、使用amalgamation型源码编译

 下载源码解压后得到四个源文件,本次解压到sqliteOne文件夹下:

[root@localhost sqlite3]# ls
sqliteOne sqlite-src-arch
[root@localhost sqlite3]# cd sqliteOne/
[root@localhost sqliteOne]# ls
shell.c sqlite3.c sqlite3ext.h sqlite3.h

2.1 使用这四个文件编译出sqlite3可执行程序:

[root@localhost sqliteOne]# gcc shell.c sqlite3.c -o sqlite3 -lpthread -ldl -lrt
[root@localhost sqliteOne]# ls
shell.c sqlite3 sqlite3.c sqlite3ext.h sqlite3.h
[root@localhost sqliteOne]# ./sqlite3
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>
\color{red}{ gcc -o指定编译生成的可执行程序名称;-l加链接的库的名称;至于为什么要指定链接这些库,主要是因为sqlite程序依赖这几个库}

2.2 将sqlite3源代码加入到自己的项目中:

2.2.1 直接使用
 将sqlite3.c、sqlite3.h、sqlite3ext.h直接加到自己的工程中,#include头文件后即可使用
2.2.2 静态链接库使用
 首先要生成libsqlite3.a静态库,然后在自己的工程中-lsqlite3静态链接该库即可

[root@localhost sqliteOne]# gcc -c sqlite3.c
[root@localhost sqliteOne]# ar -crus libsqlite3.a sqlite3.o
[root@localhost sqliteOne]# gcc test.c -L . -lsqlite3 -lpthread -lrt -ldl
[root@localhost sqliteOne]# ./a.out
Create/Open test.db success!
classno: 19061214
name: dianzi
personNum: 30
\color{red}{gcc -c将sqlite3.c仅编译不链接,生成中间sqlite3.o}
\color{red}{ar 命令将生成的.o文件打包成静态链接库libsqlite3.a}
\color{red}{gcc -L .指定链接静态库搜索当前路径,-lsqlite3链接上一步生成的静态库libsqlite3.a}

2.2.3 动态链接库使用
 首先要生成libsqlite3.so动态库,然后在自己的工程中-lsqlite3静态链接该库

[root@localhost sqliteOne]# gcc sqlite3.c -fPIC -shared -o libsqlite3.so
[root@localhost sqliteOne]# gcc test.c -L . -lsqlite3 -lpthread -lrt -ldl
[root@localhost sqliteOne]# ./a.out
./a.out: error while loading shared libraries: libsqlite3.so: cannot open shared object file: No such file or directory

生成的可执行程序运行后报错cannot open shared object file.
解决方法可以网上搜到很多解决方案,比如:

  1. 用ln将需要的so文件链接到/usr/lib或者/lib这两个默认的目录下边
    ln -s /where/you/install/lib/*.so /usr/lib

但对于有些同学linux环境受权限限制,可能没有该权限,有没有更好的办法呢?当然是有的:

[root@localhost sqliteOne]# gcc test.c -lpthread -lrt -ldl -L . -lsqlite3 -Wl,-rpath=./
[root@localhost sqliteOne]# ./a.out
Create/Open test.db success!
classno: 19061214
name: dianzi
personNum: 30

\color{red}{gcc -Wl 表示编译器将后面的参数传递给链接器ld,用rpath为程序添加一个运行时库文件搜索路径}

示例代码

test.源码如下,仅用于说明编译链接方法,实际使用尽量避免sqlite3_exec的使用,效率极其低下。

#include <stdio.h>
#include "sqlite3.h"
#include <stdlib.h>
#include <string.h>

int callback(void* data, int ncols, char** values, char** headers)  
{  
    int i;  
    int len =0;  
    int ll=0;  
    for(i=0; i < ncols; i++)  
    {  
        if(strlen(headers[i])>len)  
            len = strlen(headers[i]);  
    }  
      
    for(i=0; i < ncols; i++)   
    {  
        ll = len-strlen(headers[i]);  
        while(ll)  
        {  
            fprintf(stdout," ");  
            --ll;  
        }  
        fprintf(stdout, "%s: %s\n", headers[i], values[i]);  
    }  
  
    fprintf(stdout, "\n");  
    return 0;  
}  
int main()
{
    sqlite3 *db = NULL;
    int result;
    result = sqlite3_open("./test.db",&db);
    if(result != SQLITE_OK)
    {
        printf("Create/Open test.db error!\n");
        return -1;
    }
    printf("Create/Open test.db success!\n");


    const char* sqlStr1 = "select * from class limit 3;";
    result = sqlite3_exec(db,sqlStr1,callback,0,0);
    if(result != SQLITE_OK)
    {
        printf("select table class error!\n");
        return -1;
    }
    printf("select table class success!\n");
    sqlite3_close(db);
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容