1. 程式人生 > >SQLite3原始碼在Windows及WinCE平臺下的編譯方法

SQLite3原始碼在Windows及WinCE平臺下的編譯方法

把原始碼下下來(第一項便是),上面有這麼一句話:This ZIP archive contains all C source code for SQLite 3.7.6.2 combined into a single source file (the amalgamation). 真扯!點了那個 amalgamation,似乎說是將n多個.c和.h檔案用makefile整成了一個檔案.c檔案。不知道高人為啥這麼做,反正給研究原始碼增加了難度。好了,無論怎樣,原始碼還是有的,下下來,有四個檔案shell.c,sqlite3.c,sqlite3.h,sqlite3ext.h。那個shell.c就是shell command的原始碼了,暫時不用,那個sqlite3ext.h我也不想包含進來,所以就拷貝了sqlite3.c,sqlite3.h到一個新建的dll工程下面,將檔案新增到工程中,編譯,就知道會出錯,錯誤是:fatal error C1853: 'Debug/sqlite.pch' precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa)。看樣子時跟預編譯標頭檔案有關係,在sqlite.c中包含以下"stdafx.h",也不好使。

網上查了下,大體說是這個檔案時.c檔案,預編譯是對.cpp檔案的,可以把該.c的預編譯標頭檔案設成No,步驟是:

右擊該檔案:Properties-->C/C++-->Precompiled Headers,將選項Create/Use Precompiled Header設為:Not Using Precompiled Headers即可。再編譯,通過了。

至於預編譯標頭檔案是怎麼一回事兒,這裡就不多談了,超出了本部落格範圍(其實本人還沒徹底研究過,一般寫書都這麼說的,呵呵)。

有用資訊如下:

SQLite官方下載只提供給我們一個sqlite3.dll跟一個sqlite3.def檔案,並沒有提供用於VC++6.0的lib檔案,可以利用sqlite3.def檔案生成,步驟如下:
1.將sqlite3.h(可從原始碼目錄獲得)拷貝到C:/Program Files/Microsoft Visual Studio/VC98/Include目錄下,這時編譯可通過,但連結錯誤,因為沒有LIB檔案
2.啟動一個命令列程式,進入VC的安裝目錄C:/Program Files/Microsoft Visual Studio/VC98/Bin,在這個目錄下面有一個LIB.exe檔案,使用它就能生成sqlite3.lib檔案,將sqlite3.def檔案放到相同目錄,或者絕對路徑也可以, 然後在命令列輸入如下命令:
LIB /MACHINE:IX86 /DEF:sqlite3.def
該命令生成兩個檔案:sqlite3.lib和sqlite3.exp
執行該命令時,如果提示找不到MSPDB60.DLL檔案,可從其它目錄拷貝至Bin目錄下
3.將生成的sqlite3.lib拷貝到Lib目錄下,將sqlite3.dll拷貝到C:/WINNT/system32目錄下
5.將sqlite3.lib加入到工程連結中,Project->Settings,Link選項卡,Object/library modules最後添入sqlite3.lib這時以下程式便可通過編譯連結並執行。

不過這個是教給如何用dll和def檔案生成lib檔案的,看來download頁面還有一個下載這兩個檔案的選項,那就是Precompiled Binaries For Windows大標題下的第二項,下下來,解壓,果然就有sqlite3.dll和sqlite3.def兩個檔案。可是,我想編譯原始碼來生成dl啊!

開啟sqlite3.h一看,所有函式都不是匯出函式,沒有匯出函式,就沒有lib檔案了。再仔細一看,所有函式前面加了個巨集定義SQLITE_API,檢視該巨集,是個空,哈哈,將其定義為__declspec(dllexport),編譯,還是沒有.lib檔案。原因是什麼呢,前面說到sqlite.c是個用makefile生成的包含了所有原始檔的檔案,那就是說sqlite3.h根本沒用到,檢視sqlite.c,發現其開始出也有SQLITE_API的巨集定義,

如下:

#ifndef SQLITE_API
# define SQLITE_API 
#endif

將其改為:

#ifndef SQLITE_API
# define SQLITE_API __declspec(dllexport) 
#endif

再編譯,lib檔案終於生成了!

下面該寫一個test工程了,新建一個控制檯工程,為了簡單起見,將sqlite.dll,sqlite.lib,sqlite3.h都拷貝到test工程下面,在main()函式上面加上下面兩行:

#include "sqlite3.h"

#pragma comment(lib, "sqlite.lib")

然後,就抄那個上面說到讓我excited的程式,編譯通過。執行的時候要用到之前讀command shell manual的時候,按照上面建立的那個資料庫,把ex1資料庫拷貝到Debug目錄下,在命令列下,執行:

test ex1 "select * from tbll"

結果顯示:

one = hello!

two = 10

one = googdbye

two = 20

 我們只需要用到sqlite3.c即可,而使用sqlite類庫的時候,我們就用到sqlite3.h就可以了

下面我們來編寫個程式來測試下我們的動態連結庫.

在VC下新建一個空的"Win32 Console Application" Win32控制檯程式,工程命名為:TestSqliteOnWindows
再新建一個 test.cpp 的C++語言源程式,原始碼如下:

// name: test.cpp
// This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
// Author : zieckey
// data : 2006/11/28

#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h" 
#define _DEBUG_

int main( void )
...{
sqlite3 *db=NULL;
char *zErrMsg = 0;

int rc;

rc = sqlite3_open("zieckey.db", &db); //開啟指定的資料庫檔案,如果不存在將建立一個同名的資料庫檔案
if( rc )
...{
fprintf(stderr, "Can't open database: %s ", sqlite3_errmsg(db));
sqlite3_close(db);
return (1);
}
else printf("You have opened a sqlite3 database named zieckey.db successfully! Congratulations! Have fun ! ^-^  ");


//建立一個表,如果該表存在,則不建立,並給出提示資訊,儲存在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(ID INTEGER PRIMARY KEY,SensorID INTEGER,SiteNum INTEGER,Time VARCHAR(12),SensorParameter REAL);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );

#ifdef _DEBUG_
printf("zErrMsg = %s  ", zErrMsg);
#endif

//插入資料 
sql = "INSERT INTO "SensorData" VALUES(NULL , 1 , 1 , '200605011206', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );

sql = "INSERT INTO "SensorData" VALUES(NULL , 23 , 45 , '200605011306', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );

sql = "INSERT INTO "SensorData" VALUES(NULL , 34 , 45 , '200605011306', 15.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );


int nrow = 0, ncolumn = 0;
char **azResult; //二維陣列存放結果

//查詢資料
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
int i = 0 ;
printf( "row:%d column=%d  " , nrow , ncolumn );
printf( " The result of querying is :  " );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s ", i , azResult[i] );

//刪除資料
sql = "DELETE FROM SensorData WHERE SensorID = 1 ;" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s  ", zErrMsg);
#endif
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
printf( " row:%d column=%d " , nrow , ncolumn );
printf( " After deleting , the result of querying is :  " );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s ", i , azResult[i] );


//釋放掉 azResult 的記憶體空間
sqlite3_free_table( azResult );

#ifdef _DEBUG_
printf("zErrMsg = %s  ", zErrMsg);
#endif

sqlite3_close(db); //關閉資料庫
return 0;
}

另外,將sqlite3.h sqlite3.lib sqlite3.dll檔案複製到我們的工程目錄.
最後 Project->Settings 在Link選項卡找到Object/library modules : 在最後填入sqlite3.lib 。
如果原來就有連結,請使用空格分隔。
現在可以編譯了.
執行結果如下:
You have opened a sqlite3 database named zieckey.db successfully!
Congratulations! Have fun ! ^-^
zErrMsg = (null)
row:3 column=5

The result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 1
azResult[6] = 1
azResult[7] = 1
azResult[8] = 200605011206
azResult[9] = 18.9
azResult[10] = 2
azResult[11] = 23
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 16.4
azResult[15] = 3
azResult[16] = 34
azResult[17] = 45
azResult[18] = 200605011306
azResult[19] = 15.4
zErrMsg = (null)


row:2 column=5
After deleting , the result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 2
azResult[6] = 23
azResult[7] = 45
azResult[8] = 200605011306
azResult[9] = 16.4
azResult[10] = 3
azResult[11] = 34
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 15.4
zErrMsg = (null)
Press any key to continue

這個程式,我們先建立一個數據庫,然後新建一個表,然後插入一些資料,
再查詢看看插入的資料是否正確,然後又刪除一些資料,刪除後我們再查詢了一下,
發現我們的刪除操作也是成功的.
這個程式簡單的呼叫 sqlite 的函式介面來實現對資料庫的管理,
包括建立資料庫、建立表格、插入資料、查詢資料、刪除資料等。


注:在上面的第五步
5). 將 SQLite 原始檔中的 sqlite3.def 檔案新增到在工程的Source File中
是必須的, sqlite3.def 這個檔案的加入會生成 *.lib引入庫檔案,這個對於*.dll檔案是很重要的.否則你光有*.dll檔案在程式呼叫的時候就不是那麼方便了,因為這樣你只能通過動態載入dll的方式呼叫dll庫中函式

三、如何編譯sqlite3.4.2版本 (本人原創:添加於 2007年9月29日)

其實這個版本的比之前的更好編譯而且很簡單。

步驟如下:
1、在網站下載原始檔,選擇“sqlite-amalgamation-3_4_2.zip”下載,地址http://www.sqlite.org/sqlite-amalgamation-3_4_2.zip。此檔案中包含了sqlite3.h和sqlite3.c兩個檔案。

2、下載“sqlitedll-3_4_2.zip”,地址 http://www.sqlite.org/sqlitedll-3_4_2.zip,次檔案中包含編譯好的DLL檔案和DEF檔案,DEF檔案用來在編譯時生成lib檔案。(重點)

3、開啟VC新建一個“Win32 Dynamic-Link Library”工程,命名為:sqlite3
4、 在接下來的對話方塊中選擇"An empty DLL project",點 FINISH->OK
5、將解壓後的 *.c *.h *.def 複製到工程資料夾下
6、在工程的Source File中新增你下載到的SQLite原始檔中sqlite3.c檔案,
7、 將 SQLite 原始檔中的 sqlite3.def 檔案新增到在工程的Source File中
8、在Header File中新增你下載到的SQLite原始檔中的sqlite3.h檔案,
9、 開始編譯,Build(F7)一下