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'
为什么需要在纯pascal(或asm)中实现Borland C运行时函数?
不能直接在obj中链接那些?
其中一些已经在System.pas中实现,但编译器抱怨了吗?
做这个MysqLf而不是使用Synsqlite3或DIXml的理由如下:
> Synsqlite3支持3.7.8(我没看到最新的3.7.9)
> Synsqlite3错过了一些声明,如sqlite3_trace,sqlite_open_v2等.
>在随后的20 000步操作中,Synsqlite2比DIXml 2.4.0快约18倍
> DIsqlite3已付款
> DIsqlite 2.4.0在260ms内快速完成20000步操作,但不支持DXE2
> DIsqlite 3.0.0和3.1.0确实支持DXE2,但比2.4.0慢大约8倍
>我是一个非常好奇的人,总是试着尽可能接近金属编码.
>对Synsqlite3和DIsqlite3开发人员的称赞 – 到目前为止真的很棒
最终我最终选择了Synsqlite3,因为:
>它是开源的
>这是非常好的记录
>我学会了如何自己重新编译sqlite3.obj,并为我需要的功能留下所需的编译开关
>我可以链接更新的3.7.9版本
>通过微调最新的3.7.9 obj,我达到了DIsqlite3的速度
> DIsqlite3家伙甚至没有在他的网站上写一个电子邮件地址(只是一个邮件列表),其中Synsqlite3家伙在同一时间回复SO.选择一个lib而不是另一个lib时这是有意义的.性能和价格并非一切.
解决方法
以下是我们如何将源代码编译成.obj(一个包含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 System.@Trunc // FST(0) -> EDX:EAX,as expected by BCC32 compiler end; function _ftoul: Int64; // Borland C++ float to integer (Int64) conversion asm jmp System.@Trunc // 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^,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 System.@_lldiv end; procedure _lludiv; asm jmp System.@_lludiv end; procedure _llmod; asm jmp System.@_llmod end; procedure _llmul; asm jmp System.@_llmul end; procedure _llumod; asm jmp System.@_llumod end; procedure _llshl; asm jmp System.@_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 System.@_llshr {$endif} end; procedure _llushr; asm jmp System.@_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.