天天看點

【物聯網智能網關-16】成功移植SQLite(STM32 .NET MF平台)

前言

.NET Micro Framework系統官方代碼是不支援任何資料庫的,這對一些具有使用者管理的Web Server、RFID資料采集和複雜的手持機應用來說是非常不友善的。

确定了要移植SQLite資料庫,但是又引出一個問題,是移植SQLite最新的版本?還是以前相對代碼較小的版本?這着實讓我躊躇了良久。

項目

V2.8.17

V3.7.15

API接口個數

44

207

源檔案個數

89

源代碼位元組數

1.32M

4.0M

Win32 dll庫大小

209K

591K

文本編碼支援

UTF-8或iso8859

UTF-8、UTF-16

二進制資料(Blob)

支援

行編号

32位元組

64位元組

并發性

多讀,單寫

改良的并發性

.NET Micro Framework的核心代碼也不過300K左右,如果支援一個比自己核心還大的多的資料庫,真有點小馬拉大車的感覺,是以在滿足基本功能的基礎上(以前我比較擔心V2x版本的國際化應用,比如是否支援中文),代碼大小是我最關注的。

在Windows平台上對SQLiteV2.8.17進行測試後,決定移植V2x版本的SQLite(當然後續不排除再移植3.0版本),移植成功後,release版本的 SQLite的大小大概130K左右。

SQLite V2x和V3x .NET Framework開發

考慮到.NET Micro Framework是.NET架構,是以最初研究的是System.Data.SQLite.dll庫,後來發現,一是System.Data.SQLite.dll封裝的太過複雜,二是System.Data.SQLite.dll對.NET Framework的架構非常依賴,并且針對不同平台,很難做到直接拷貝就可以使用(必須要安裝),三是沒有支援SQLite V2x的版本。

是以最後還是決定用Interop的方式直接通路Win32 的 SQLite.dll。網上搜尋了一下,有關于SQLite3的相關示例,SQLite V2x的就沒有了。是以先研究了一下SQLite3的接口應用,然後根據C++相關的接口定義,反推了一下SQLite V2x的C#接口。

在Windows .NET Framework平台測試SQLite V2x接口(如下圖)沒有問題的情況下,才開始進行.NET Micro Framework 平台下的SQLite V2x的移植。

SQLite V2x .NET Micro Framework移植

理論情況下,隻需要對OS.c代碼中的接口進行.NET MF的實作即可(标準的OS.c檔案已經支援Windows,UNIX、Mac OS平台)。但實際移植發現,遠沒有這麼簡單。

(1)、SQLite代碼都是标準的C語言,但是OS.c中需要調用.NET MF本身的C++代碼操作接口,是以SQLite所有源碼的c擴充名一律修改為cpp接口,采用cpp編譯器進行編譯,但是這樣修改後,會出現很多編譯錯誤,大都是類型轉換的錯誤。

(2)、.NET Micro Framework平台不支援(或不建議)直接采用标準的string.h、ctype.h、math.h和stdio.h等頭檔案定義的函數。.NET Micro Framework代碼中已經有部分字元串操作的實作,但是為了實作SQLite的正确編譯,還必須自己補全相關操作函數。時間、檔案等操作函數,也需要轉換為.NET Micro Framework平台下的,或者自己實作。

(3)、記憶體配置設定相關函數.NET MicroFramework有兩類,一種就是private_開頭的函數,另外就是TinyCLR支援的記憶體操作函數,由于二者使用的堆空間不同(private_開頭的操作Custom_Heap,這個一般都比較小),是以我調試的時候采用private_開頭的函數,實際應用則是TinyCLR記憶體操作函數。把SQLite記憶體相關操作的函數,修改為.NET MicroFramework的。

(4)、由于.NET Micro Framework底層代碼對檔案的操作相對簡單,是以SQLite産生的臨時檔案,我是在上層C#代碼中進行清除的。

(5)、鎖操作,.NET MicroFramework底層是無法對檔案進行鎖定操作的,考慮到.NETMicro Framework本身的特點(單程序,多線程),是以在上層C#代碼中進行了簡單的鎖實作(該鎖讀寫不能同時)。

(6)、SQLite指針應用的非常多,稍有不慎,系統就會出異常,是以在移植過程中,一定要研究透各種接口指針的實際含義(比如定義char ***p這類指針,我以前就很少遇到) ,否則調試過程将是一個噩夢。

SQLite.NET MF應用開發

   .NETMF C#接口又進行了封裝,一是接口盡可能和System.Data.SQLite.dll相容,二是做一些必要的記憶體釋放和其它處理(如系統格式化,建立臨時目錄,磁盤重新整理等等)。

   其實對相對簡單的嵌入式應用來說,資料庫無非就是建表,添加和修改資料,删除,擷取表資料而已,而這些功能都可以通過SQL語句進行實作,是以說功能多,但是接口卻很簡單(如下圖所示)。

測試代碼如下:

    public  static void Main()

    {

        stringdbPath = "\\ROOT\\mftest.db";

        using (SQLite db = new SQLite(dbPath)) //":memory:"))

        {

            //建立表

            db.ExecuteNonQuery("CREATE TABLE student(id INTEGER, name VARCHAR(20),sex VARCHAR(2));");

            //插入資料

            db.ExecuteNonQuery("INSERT INTO student VALUES(1, '小紅', '女');");

            db.ExecuteNonQuery("INSERT INTO student VALUES(2, '小李', '男');");

            db.ExecuteNonQuery("INSERT INTO student VALUES(3, '小明', '男');");

            //讀取表

            YFDataTabletable = db.ExecuteQuery("SELECT * FROMstudent"); // WHERE name = '小李';");

            stringinfo = "";

            foreach(YFColumn col intable.Columns)

            {

                info += col.Name + " ";

            }

            Debug.Print(info);

            foreach(YFDataRow row intable.Rows)

                Debug.Print(row[0].ToString()+ "," + row[1] + "," + row[2]);

            }

        }

        Thread.Sleep(Timeout.Infinite);

    }

運作調試的場景如下圖所示:

 -----------------------------------------------------------------------------------------

<a href="http://weibo.com/1804832611?s=6uyXnP"></a>