2012-01-01 93 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