2012-01-01 91 views
8

我曾嘗試使用下面的命令編譯SQLITE3數據庫引擎從sqlite3.c與BCC 55:鏈接sqlite3.obj發出uunsatisfied向前聲明錯誤

bcc32.exe -jb -O2 -w- -K -c -6 -u- sqlite3.c 

生成正確sqlite3.obj文件。但是,一旦我嘗試在我的Delphi應用程序這樣的鏈接:

unit unt_SQLite3; 

interface 

uses 
    Windows; 

implementation 

{$LINK 'sqlite3.obj'} 
end. 

我收到以下錯誤:

[DCC Error] E2065 Unsatisfied forward or external declaration: '__ftol' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__lldiv' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llmod' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_localtime' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_strncmp' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memset' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llmul' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_malloc' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_free' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_realloc' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memcpy' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llumod' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__lludiv' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memmove' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_memcmp' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llshl' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llshr' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_atol' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_strlen' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '_qsort' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__llushr' 
[DCC Error] E2065 Unsatisfied forward or external declaration: '__turboFloat' 

實現了Borland C++純帕斯卡運行時函數爲什麼需要(或ASM )? 不能在obj中直接鏈接嗎? 其中一些已經在System.pas中實現,但編譯器抱怨?

這樣做背後mysqlf而不是使用SynSQLite3或DIXml合理如下:

  • SynSQLite3支持3.7.8(我沒有看到最新的3.7.9)

  • SynSQLite3失誤像sqlite3_trace,sqlite_open_v2等一些聲明

  • SynSQLite2是在隨後的20個000步驟操作要比DIXml 2.4.0慢約18倍

  • DISQLite3支付

  • DISQLite 2.4.0是快?20000個操作在260ms,但不支持DXE2

  • DISQLite 3.0.0和3.1.0做支撐DXE2但都是圍繞慢8倍比2.4.0更好

  • 我非常好奇,總是試着儘可能接近金屬代碼。

  • 榮譽給SynSQLite3和DISQLite3開發商 - 真正的好工作DOEN到目前爲止

最後,我最終選擇SynSQLite3因爲

  1. 它是開源的

  2. 這是非常有據可查的

  3. 我學會了如何重新編譯sqlite3.obj自己,只留下需要的編譯開關,用於我需要

  4. 我可以有更新的3.7.9版本聯

  5. 隨着調整最新3.7的優良特性.9 obj我達到了DISQLite3的速度

  6. DISQLite3的傢伙在他的網站上甚至沒有寫郵件的地址(只是一個郵件列表),SynSQLite3人員在同一小時內在SO中回覆。當選擇一個庫到另一個庫時這是有意義的。性能和價格不是一切。

SQLite3 Profile Results

附:我sqlite3.obj是temporaly可供下載和測試here

+0

接頭。編譯器不關心,鏈接器。 – OnTheFly 2012-01-01 21:06:37

+0

@user no,這是dcu編譯時的編譯時間 – 2012-01-01 21:15:05

+0

@DavidHeffernan,不真實。 – OnTheFly 2012-01-01 22:48:24

回答

8

看看我們的開源庫。它實現了sqlite3.obj的靜態鏈接,並且使用最新版本的SQLite3官方代碼(和功能 - 它是唯一允許擴展使用SQLite3虛擬表的框架)來維護。你有一個包裝。但不止於此。

下面是我們如何編譯源到.OBJ(一個inclusing FTS3,其他沒有的話):

del sqlite3.obj 
\dev\bcc\bin\bcc32 -6 -O2 -c -d -DSQLITE_ENABLE_FTS3 -u- sqlite3.c 
copy sqlite3.obj sqlite3fts3.obj 
\dev\bcc\bin\bcc32 -6 -O2 -c -d -u- sqlite3.c 

然後看看在SynSQLite3.pas單元。它包含一些純粹的pascal或asm版本的所需外部文件。

例如:

function _ftol: Int64; 
// Borland C++ float to integer (Int64) conversion 
asm 
    jmp [email protected] // FST(0) -> EDX:EAX, as expected by BCC32 compiler 
end; 

function _ftoul: Int64; 
// Borland C++ float to integer (Int64) conversion 
asm 
    jmp [email protected] // FST(0) -> EDX:EAX, as expected by BCC32 compiler 
end; 

function malloc(size: cardinal): Pointer; cdecl; { always cdecl } 
// the SQLite3 database engine will use the FastMM4/SynScaleMM fast heap manager 
begin 
    GetMem(Result, size); 
end; 

procedure free(P: Pointer); cdecl; { always cdecl } 
// the SQLite3 database engine will use the FastMM4 very fast heap manager 
begin 
    FreeMem(P); 
end; 

function realloc(P: Pointer; Size: Integer): Pointer; cdecl; { always cdecl } 
// the SQLite3 database engine will use the FastMM4/SynScaleMM very fast heap manager 
begin 
    result := P; 
    ReallocMem(result,Size); 
end; 

function memset(P: Pointer; B: Integer; count: Integer): pointer; cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
begin 
    result := P; 
    FillChar(P^, count, B); 
end; 

procedure memmove(dest, source: pointer; count: Integer); cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
begin 
    Move(source^, dest^, count); // move() is overlapping-friendly 
end; 

procedure memcpy(dest, source: Pointer; count: Integer); cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
begin 
    Move(source^, dest^, count); 
end; 

function atol(P: pointer): integer; cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
begin 
    result := GetInteger(P); 
end; 

var __turbofloat: word; { not used, but must be present for linking } 

// Borland C++ and Delphi share the same low level Int64 _ll*() functions: 

procedure _lldiv; 
asm 
    jmp [email protected]_lldiv 
end; 

procedure _lludiv; 
asm 
    jmp [email protected]_lludiv 
end; 

procedure _llmod; 
asm 
    jmp [email protected]_llmod 
end; 

procedure _llmul; 
asm 
    jmp [email protected]_llmul 
end; 

procedure _llumod; 
asm 
    jmp [email protected]_llumod 
end; 

procedure _llshl; 
asm 
    jmp [email protected]_llshl 
end; 

procedure _llshr; 
asm 
{$ifndef ENHANCEDRTL} // need this code for Borland/CodeGear default System.pas 
    shrd eax, edx, cl 
    sar  edx, cl 
    cmp  cl, 32 
    jl  @@Done 
    cmp  cl, 64 
    jge  @@RetSign 
    mov  eax, edx 
    sar  edx, 31 
    ret 
@@RetSign: 
    sar  edx, 31 
    mov  eax, edx 
@@Done: 
{$else} 
    // our customized System.pas didn't forget to put _llshr in its interface :) 
    jmp [email protected]_llshr 
{$endif} 
end; 

procedure _llushr; 
asm 
    jmp [email protected]_llushr 
end; 

function strlen(p: PAnsiChar): integer; cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
begin // called only by some obscure FTS3 functions (normal code use dedicated functions) 
    result := SynCommons.StrLen(pointer(p)); 
end; 

function memcmp(p1, p2: pByte; Size: integer): integer; cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
begin 
    if (p1<>p2) and (Size<>0) then 
    if p1<>nil then 
     if p2<>nil then begin 
     repeat 
      if p1^<>p2^ then begin 
      result := p1^-p2^; 
      exit; 
      end; 
      dec(Size); 
      inc(p1); 
      inc(p2); 
     until Size=0; 
     result := 0; 
     end else 
     result := 1 else 
    result := -1 else 
    result := 0; 
end; 

function strncmp(p1, p2: PByte; Size: integer): integer; cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
var i: integer; 
begin 
    for i := 1 to Size do begin 
    result := p1^-p2^; 
    if (result<>0) or (p1^=0) then 
     exit; 
    inc(p1); 
    inc(p2); 
    end; 
    result := 0; 
end; 


function localtime(t: PCardinal): pointer; cdecl; { always cdecl } 
// a fast full pascal version of the standard C library function 
var uTm: TFileTime; 
    lTm: TFileTime; 
    S: TSystemTime; 
begin 
    Int64(uTm) := (Int64(t^) + 11644473600)*10000000; // unix time to dos file time 
    FileTimeToLocalFileTime(uTM,lTM); 
    FileTimeToSystemTime(lTM,S); 
    with atm do begin 
    tm_sec := S.wSecond; 
    tm_min := S.wMinute; 
    tm_hour := S.wHour; 
    tm_mday := S.wDay; 
    tm_mon := S.wMonth-1; 
    tm_year := S.wYear-1900; 
    tm_wday := S.wDayOfWeek; 
    end; 
    result := @atm; 
end; 

你會發現在這個單元比SQLite3的只是一個靜態鏈接等等。請注意,即使它由我們的mORMot ORM客戶端 - 服務器框架使用,該ORM也是而不是,因此需要使用SQLite3類。見this article for additional details

如果您丟失到我們的源代碼庫(使用偉大的FOSSIL項目),read this

+0

+1更適合使用現有代碼的地方。 – 2012-01-01 19:37:46

+0

最後,我終於自己重新編譯sqlite3.c版本3.7.9文件,並替換SynSQLite3中的3.7.8 sqlite3.obj文件。這使得執行與DISQlite3 2.4.0版本相同。在問題中附帶分析的截圖。 – 2012-01-01 23:31:59

+0

當前版本中提供的sqlite3.obj文件已經在3.7.9中。請參閱我提供的鏈接(http://synopse.info/fossil/wiki?name=Get+the+source)。直接下載[從這裏](http://synopse.info/files/sqlite3obj.7z)。這是快照版本 - 官方1.15仍在使用3.7.8。非常感謝您對開放源代碼的興趣!如果您想加入該項目,歡迎在我們的論壇上提交一些代碼來增強該單元。 – 2012-01-02 08:19:23

4

更新:你會好得多有SynSQLite3.pas由阿爾諾建議。不過,我在這裏留下了這個答案,因爲它說明了一些可用於解決靜態鏈接時缺失依賴關係的技巧。


這裏發生的事情是.obj文件依賴於需要由您提供的各種C運行時功能。

要做的第一件事是將crtl添加到包含$LINK指令的單元的uses子句中。 crtl單元包含許多C運行時庫函數的實現,並專爲此目的而設計。

但是,當你這樣做的時候,雖然一些缺失的依賴關係被解決了,但更多的出現。

Unsatisfied forward or external declaration: '_lldiv' 
Unsatisfied forward or external declaration: '_llmod' 
Unsatisfied forward or external declaration: 'localtime' 
Unsatisfied forward or external declaration: '_llmul' 
Unsatisfied forward or external declaration: 'InterlockedCompareExchange' 
Unsatisfied forward or external declaration: 'InitializeCriticalSection' 
Unsatisfied forward or external declaration: 'Sleep' 
Unsatisfied forward or external declaration: 'DeleteCriticalSection' 
Unsatisfied forward or external declaration: 'EnterCriticalSection' 
Unsatisfied forward or external declaration: 'LeaveCriticalSection' 
Unsatisfied forward or external declaration: '_llumod' 
Unsatisfied forward or external declaration: '_lludiv' 
Unsatisfied forward or external declaration: 'GetVersionExA' 
Unsatisfied forward or external declaration: 'MultiByteToWideChar' 
Unsatisfied forward or external declaration: 'WideCharToMultiByte' 
Unsatisfied forward or external declaration: 'AreFileApisANSI' 
Unsatisfied forward or external declaration: 'FormatMessageW' 
Unsatisfied forward or external declaration: 'LocalFree' 
Unsatisfied forward or external declaration: 'FormatMessageA' 
Unsatisfied forward or external declaration: 'SetFilePointer' 
Unsatisfied forward or external declaration: 'CloseHandle' 
Unsatisfied forward or external declaration: 'ReadFile' 
Unsatisfied forward or external declaration: 'WriteFile' 
Unsatisfied forward or external declaration: 'SetEndOfFile' 
Unsatisfied forward or external declaration: 'FlushFileBuffers' 
Unsatisfied forward or external declaration: 'GetFileSize' 
Unsatisfied forward or external declaration: 'LockFileEx' 
Unsatisfied forward or external declaration: 'LockFile' 
Unsatisfied forward or external declaration: 'UnlockFile' 
Unsatisfied forward or external declaration: 'UnlockFileEx' 
Unsatisfied forward or external declaration: 'UnmapViewOfFile' 
Unsatisfied forward or external declaration: 'CreateFileMappingA' 
Unsatisfied forward or external declaration: 'MapViewOfFile' 
Unsatisfied forward or external declaration: 'GetTempPathW' 
Unsatisfied forward or external declaration: 'GetTempPathA' 
Unsatisfied forward or external declaration: 'CreateFileW' 
Unsatisfied forward or external declaration: 'CreateFileA' 
Unsatisfied forward or external declaration: 'GetFileAttributesW' 
Unsatisfied forward or external declaration: 'DeleteFileW' 
Unsatisfied forward or external declaration: 'GetFileAttributesA' 
Unsatisfied forward or external declaration: 'DeleteFileA' 
Unsatisfied forward or external declaration: 'GetFileAttributesExW' 
Unsatisfied forward or external declaration: 'GetFullPathNameW' 
Unsatisfied forward or external declaration: 'GetFullPathNameA' 
Unsatisfied forward or external declaration: 'GetDiskFreeSpaceW' 
Unsatisfied forward or external declaration: 'GetDiskFreeSpaceA' 
Unsatisfied forward or external declaration: 'LoadLibraryW' 
Unsatisfied forward or external declaration: 'LoadLibraryA' 
Unsatisfied forward or external declaration: 'GetProcAddress' 
Unsatisfied forward or external declaration: 'FreeLibrary' 
Unsatisfied forward or external declaration: 'GetSystemTime' 
Unsatisfied forward or external declaration: 'GetCurrentProcessId' 
Unsatisfied forward or external declaration: 'GetTickCount' 
Unsatisfied forward or external declaration: 'QueryPerformanceCounter' 
Unsatisfied forward or external declaration: 'GetSystemTimeAsFileTime' 
Unsatisfied forward or external declaration: 'GetSystemInfo' 
Unsatisfied forward or external declaration: '_llshl' 
Unsatisfied forward or external declaration: '_llushr' 

許多是簡單的Windows API函數,並可以很容易地通過增加Windows你使用條款來解決。

此時你只剩下以下幾點:

Unsatisfied forward or external declaration: '_lldiv' 
Unsatisfied forward or external declaration: '_llmod' 
Unsatisfied forward or external declaration: 'localtime' 
Unsatisfied forward or external declaration: '_llmul' 
Unsatisfied forward or external declaration: '_llumod' 
Unsatisfied forward or external declaration: '_lludiv' 
Unsatisfied forward or external declaration: '_llshl' 
Unsatisfied forward or external declaration: '_llushr' 

要解決這些,你需要:

  1. 鏈接包含丟失依賴另一個obj文件。
  2. 在包含$LINK的同一單元中的Delphi代碼中實現丟失的依賴關係。

我不確定這些功能是幹什麼的,所以你有更多的工作要做。我的猜測是這些函數是64位整數算術例程。您可以通過寫入C的短位來執行各種64位算術運算來逆向工程。然後使用bcc32編譯並查看輸出爲asm。據推測,bcc32有能力發射asm。或者你可以鏈接到德爾福單位,看看上述哪些功能對應於你在C代碼中使用的操作。

您可以從msvcrt.dll中拉出localtime,對於缺少的C運行時功能,這總是一個有用的後退選項。事實上,這就是目前crtl設備的實施方式,所以如果您打算使用crtl,您可能也會以同樣的方式獲得localtime


中借鑑阿爾諾一些代碼,下列單位成功編譯:

unit sqlite3; 

interface 

implementation 

uses 
    crtl, Windows; 

{$L c:\desktop\sqlite3.obj} 

procedure _lldiv; 
asm 
    jmp [email protected]_lldiv 
end; 

procedure _llmod; 
asm 
    jmp [email protected]_llmod 
end; 

procedure _llmul; 
asm 
    jmp [email protected]_llmul 
end; 

procedure _llumod; 
asm 
    jmp [email protected]_llumod 
end; 

procedure _lludiv; 
asm 
    jmp [email protected]_lludiv 
end; 

procedure _llshl; 
asm 
    jmp [email protected]_llshl 
end; 

procedure _llushr; 
asm 
    jmp [email protected]_llushr 
end; 

procedure localtime; cdecl; external 'msvcrt.dll'; 

end. 

請注意,您不需要提供參數列表,調用約定等任何這些功能,因爲我們是在這裏沒有實現它們。在每種情況下,代碼只是委託實現。

但是,這仍然缺少聲明sqlite3函數的代碼。更重要的是,我甚至沒有試圖測試它是否有效。成功編譯只是第一步。

我強烈建議您使用Arnaud指引您使用的代碼,如果您希望使用靜態鏈接。這段代碼顯然有很多使用和測試,你也可以從中受益。


靜態鏈接使得部署變得方便,但是動態鏈接到DLL要簡單得多。

+0

這些函數是64位整數的幫助器(帶符號和「u」標記)。在gcc系統上,這些函數在libgcc中。可能需要從msvc對象文件靜態鏈接。 – 2012-01-01 21:57:04

+0

我可能會因爲意外而低估了你的回覆率。如果是我,請讓我知道要糾正。如果不是我,請刪除此評論。 – 2012-01-01 23:33:37

+1

在Delphi XE2中,可以使用System.Win.Crtl.pas這個名字命名crtl單元,並且可以在C:\ Program Files \ Embarcadero \ RAD Studio \ 9.0 \ source \ rtl \ common下使用源代碼。使用安裝路徑。在以前的XE版本中,它僅作爲crtl.dcu提供。 – 2012-01-01 23:36:00