1. 程式人生 > >CPP檔案和C檔案混編和將sqlite3加入自己的c++工程

CPP檔案和C檔案混編和將sqlite3加入自己的c++工程

今天嘗試將使用sqlite3資料庫,直接使用sqlite3的原始碼,得到sqlite3.c和sqlite3.h。

我想將他們加入到我的cpp工程裡面

所以我新建了一個mysqlite3.cpp檔案,在裡面呼叫了sqlite3的函式。

下面來說明我遇到的問題及解決方法

一共有兩種編譯方法,一種使用gcc/g++編譯,一種使用cmake編譯,下面就來說明這兩種方法

工程原始碼在最後面。

第一種:使用gcc/g++編譯

1.g++ mysqlite.cpp sqlite3.c -o a.out

直接報了一大堆invalid use of incomplete type "XXX"的錯誤。

解決方法就是.cpp檔案和.c檔案要分開編譯,分別用gcc和g++編譯成.o,再用g++將多個.o連線起來

2.gcc -c sqlite3.c -o sqlite3.o

也是報了一堆,對‘pthread_create’未定義的引用,表示找不到pthread_create等函式,應該是沒有連線執行緒庫檔案

解決辦法,加上 -lpthread

3.gcc -c sqlite3.c -o sqlite3.o -lpthread

又報了一堆對‘dlopen’未定義的引用,表示找不到dl庫

解決辦法,加上-ldl

4.gcc -c sqlite3.c -o sqlite3.o -lpthread -ldl

成功生成sqlite3.o

5.g++ -c mysqlite.cpp -o mysqlite.o

一次成功,生成mysqlite3.o

6.g++ mysqlite.o sqlite3.o -o a.out

報了pthread和dl的未定義的引用,加上

7.g++ mysqlite.o sqlite3.o -o a.out -lpthread -ldl

成功生成a.out

8.執行a.out

OKOKOK

第二種:使用cmake編譯

cmake的安裝可看別的部落格

!!!cmake很好用,真的很好用,沒學過的一定要學

1.同樣是找不到pthread和dl

CMakeLists.txt原始碼如下

cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(apple ${SRC_LIST})

新增pthread庫和dl庫

2.成功

CMakeLists.txt原始碼如下

cmake_minimum_required(VERSION 2.8)
link_libraries(pthread)
link_libraries(dl)
aux_source_directory(. SRC_LIST)
add_executable(apple ${SRC_LIST})

成功生成apple可執行檔案


下面附上工程原始碼

sqlite3.c和sqlite3.h就不貼了,就貼我自己寫的mysqlite3.cpp

單個函式

1.開啟資料庫檔案

int DbOpen(const char * addr)	//開啟資料庫,不存在,就建立一個同名的
{
	int ret = 0;
	ret = sqlite3_open(addr,&database);
	printf("open : %d\n", ret);
	if(ret != SQLITE_OK){
		return -1;
	}
	return 0;
}

2.建立資料表

int DbCreateTbl()	
{
	int rc = sqlite3_exec(database, "create table tblTest(id int, name varchar(128));", 0, 0, &errMsg);
    //加上容錯
	printf("errMSG = %s\n",errMsg);
	return 0;
}

3.插入資料

int DbInsert()	//插入資料
{
	int rc = sqlite3_exec(database, "insert into tblTest values(1,'隨便');", 0, 0, &errMsg);
    //加上容錯
	return 0;
}

4.利用回撥函式查詢資料

//每查到一條記錄,就執行該回調函式
//para是sqlite3裡面傳入的值,現在我們傳入了0
//nCount是這一條記錄有幾個欄位
//pValue查詢到的資料都在這裡
//pName表示這個欄位的欄位名稱
//沒找到一個記錄,會呼叫一次該函式,別忘記最後的return。
int callback(void*para , int nCount, char** pValue, char** pName)	
{
	for(int i=0;i<nCount;i++){
		printf("nCount = %d,pValue = %s,pName = %s\n", nCount,pValue[i], pName[i]);
	}
	return 0;
}

int DbSearch_1()	//使用回撥函式查詢
{
	
	int rc = sqlite3_exec(database, "select * from tblTest where id = 3;", callback, 0, &errMsg);
	//加容錯
	
	return 0;
}

5.利用sqlite3_get_table查詢資料

int DbSearch_2()	//利用sqlite3_get_table查詢資料
{
	char** pResult;
	int nRow;
	int nCol;
	int rc = sqlite3_get_table(database,"select * from tblTest where id = 3;",&pResult,&nRow,&nCol,&errMsg);	
	if (rc != SQLITE_OK)  
	{   
		sqlite3_free(errMsg);
		sqlite3_close(database); 	  
		return -1;  
	}
	printf("nRow = %d,nCol = %d\n",nRow, nCol);
    //for(int i=0;i<(nRow+1) * nCol;i++) 得到表中查詢結果的所有資料
    //for(int i=col;i<(nRow+1) * nCol;i++) 得到查詢結果去除表頭所有資料
    //for(int i=nCol;i<(nRow+1) * nCol;i=i+nCol)	去除表頭得到結果集的第一列結果
    //for(int i=nCol+1;i<(nRow+1) * nCol;i=i+nCol)	去除表頭得到結果集的第二列結果
	for(int i=nCol;i<(nRow+1) * nCol;i=i+nCol)
	{
		printf("id = %s,",pResult[i]);
		printf("name = %s\n",pResult[i+1]);
	}
	
	return 0;
}

6.利用sqlite3_prepare、sqlite3_step查詢資料

int DbSearch_3()	//利用sqlite3_prepare、sqlite3_step查詢資料
{
	sqlite3_stmt *stmt = NULL;
	const char *zTail;
	if(sqlite3_prepare_v2(database, "select * from tblTest where id = 3;", -1, &stmt, &zTail) == SQLITE_OK)
	{	
		while(sqlite3_step(stmt) == SQLITE_ROW)	//不包括列標題
		{
			int id = sqlite3_column_int(stmt, 0);	//表示第一列
			const unsigned char *name = sqlite3_column_text(stmt, 1);	//表示第二列
			printf("id = %d, name = %s\n", id, name);
		}
	}
	sqlite3_finalize(stmt);
	
	
	return 0;
}

7.關閉資料庫

int DbClose()	//關閉資料庫
{
	sqlite3_free(errMsg);
	sqlite3_close(database);
	return 0;
}

總的檔案

#include "sqlite3.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <string.h>
#include <cstring>

using namespace std;
int DbOpen(const char * addr);		//開啟資料庫檔案,如果沒有同名的,則新建立一個
int DbClose();						//關閉資料庫
int DbCreateTbl();					//在資料庫檔案中建立資料表,如果存在同名的,則不會建立
int DbInsert();						//插入資料
int callback(void*para , int nCount, char** pValue, char** pName);	//回撥函式
int DbSearch_1();					//利用回撥函式查詢資料
int DbSearch_2();					//利用sqlite3_get_table查詢資料
int DbSearch_3();					//利用sqlite3_prepare、sqlite3_step查詢資料

sqlite3 *database = NULL;
char * errMsg = NULL;
int main()
{
	DbOpen("aaa");
	DbCreateTbl();
	DbInsert();
	DbSearch_1();
	printf("--------------------------\n");
	DbSearch_2();
	printf("--------------------------\n");
	DbSearch_3();
	printf("--------------------------\n");
	DbClose();
	return 0;
}

//每查到一條記錄,就執行該回調函式
//para是sqlite3裡面傳入的值,現在我們傳入了0
//nCount是這一條記錄有幾個欄位
//pValue查詢到的資料都在這裡
//pName表示這個欄位的欄位名稱
//沒找到一個記錄,會呼叫一次該函式,別忘記最後的return。
int callback(void*para , int nCount, char** pValue, char** pName)	
{
	for(int i=0;i<nCount;i++){
		printf("nCount = %d,pValue = %s,pName = %s\n", nCount,pValue[i], pName[i]);
	}
	return 0;
}

int DbSearch_1()	//使用回撥函式查詢
{
	
	int rc = sqlite3_exec(database, "select * from tblTest where id = 3;", callback, 0, &errMsg);
	//加容錯
	return 0;
}

int DbSearch_2()	//利用sqlite3_get_table查詢資料
{
	char** pResult;
	int nRow;
	int nCol;
	int rc = sqlite3_get_table(database,"select * from tblTest where id = 3;",&pResult,&nRow,&nCol,&errMsg);	
	if (rc != SQLITE_OK)  
	{   
		sqlite3_free(errMsg);
		sqlite3_close(database); 	  
		return -1;  
	}
	printf("nRow = %d,nCol = %d\n",nRow, nCol);
	for(int i=nCol;i<(nRow+1) * nCol;i=i+nCol)
	{
		printf("id = %s,",pResult[i]);
		printf("name = %s\n",pResult[i+1]);
	}
	return 0;
}

int DbSearch_3()	//利用sqlite3_prepare、sqlite3_step查詢資料
{
	sqlite3_stmt *stmt = NULL;
	const char *zTail;
	if(sqlite3_prepare_v2(database, "select * from tblTest where id = 3;", -1, &stmt, &zTail) == SQLITE_OK)
	{	
		while(sqlite3_step(stmt) == SQLITE_ROW)	//不包括列標題
		{
			int id = sqlite3_column_int(stmt, 0);	//表示第一列
			const unsigned char *name = sqlite3_column_text(stmt, 1);	//表示第二列
			printf("id = %d, name = %s\n", id, name);
		}
	}
	sqlite3_finalize(stmt);
	return 0;
}

int DbInsert()	//插入資料
{
	int rc = sqlite3_exec(database, "insert into tblTest values(1,'隨便');", 0, 0, &errMsg);
	return 0;
}

//建立一張資料表,如果存在同名數據表,則errMSG = table tblTest already exists。繼續執行
int DbCreateTbl()	
{
	int rc = sqlite3_exec(database, "create table tblTest(id int, name varchar(128));", 0, 0, &errMsg);
	printf("errMSG = %s\n",errMsg);
	return 0;
}

int DbOpen(const char * addr)	//開啟資料庫,不存在,就建立一個同名的
{
	int ret = 0;
	ret = sqlite3_open(addr,&database);
	printf("open : %d\n", ret);
	if(ret != SQLITE_OK){
		return -1;
	}
	return 0;
}

int DbClose()	//關閉資料庫
{
	sqlite3_free(errMsg);
	sqlite3_close(database);
	return 0;
}