2012-01-01 6 views
8

ho compilato motore di database sqlite3 da sqlite3.c con BCC 55 utilizzando il seguente comando:Collegamento sqlite3.obj emette uunsatisfied avanti errori dichiarazioni

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

Il file sqlite3.obj corretta è stato generato. Ma una volta che provo a collegarlo nella mia richiesta di Delfi in questo modo:

unit unt_SQLite3; 

interface 

uses 
    Windows; 

implementation 

{$LINK 'sqlite3.obj'} 
end. 

Ottengo i seguenti errori:

[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' 

Perché è necessario per implementare le funzioni di runtime in puro Pascal di Borland C++ (o asm)? Non sono direttamente collegati quelli nell'obj? Alcuni di questi sono già implementati in System.pas ma il compilatore si lamenta ancora?

Il razionale dietro a fare questo mysqlf invece di utilizzare SynSQLite3 o DIXml è il seguente:

  • SynSQLite3 supporta 3.7.8 (non vedo le ultime 3.7.9)

  • manca SynSQLite3 alcune dichiarazioni come sqlite3_trace, sqlite_open_v2, ecc

  • SynSQLite2 è circa 18 volte più lento DIXml 2.4.0 in conseguenti 20 000 operazioni passo

  • DISQLite3 è pagato

  • DISQLite 2.4.0 è veloce fa 20000 operazioni passo in 260ms, ma non supporta DXE2

  • DISQLite 3.0.0 e 3.1.0 supportano DXE2 ma sono circa 8 volte più lento di 2.4.0

  • Sono un ragazzo molto curioso e cerco sempre di codificare il più vicino possibile al metallo.

  • Complimenti agli sviluppatori SynSQLite3 e DISQLite3 - davvero un buon lavoro doen finora

Alla fine ho finito per scegliere SynSQLite3 perché:

  1. E 'open source

  2. E 'molto ben documentato

  3. ho imparato a ricompilare sqlite3.obj me stesso e lasciare solo gli switch di compilazione necessarie per le caratteristiche di cui ho bisogno

  4. posso avere la versione aggiornata 3.7.9 versione legata

  5. Con la sintonia fine ultimo 3.7 0,9 obj ho raggiunto la velocità di DISQLite3

  6. il ragazzo DISQLite3 non ha nemmeno un indirizzo email sul suo sito di scrivere (solo una mailing list), dove i ragazzi SynSQLite3 rispondono a SO sullo stesso ora.Questo ha senso quando si sceglie una lib piuttosto che un'altra. Le prestazioni e il prezzo non sono tutto.

SQLite3 Profile Results

P.S. Il mio sqlite3.obj è temporaneamente disponibile per il download e il test here

+0

Linker. Il compilatore non si preoccupa di ciò, fa il linker. – OnTheFly

+0

@user no, questo è il momento della compilazione quando viene eseguita la dcu –

+0

@DavidHeffernan, non vero. – OnTheFly

risposta

8

Dai un'occhiata alle nostre librerie Open Source. Implementa il collegamento statico di sqlite3.obj e viene mantenuto con l'ultima versione del codice ufficiale di SQLite3 (e funzionalità - è l'unica struttura che consente l'uso esteso delle Tabelle Virtuali SQLite3, ad esempio). Hai un involucro. Ma più di questo.

Ecco come si compila la fonte in obj (uno inclusing FTS3, l'altra senza):

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 

Dai un'occhiata presso l'unità SynSQLite3.pas. Contiene una versione pura pascal o asm dei file esterni necessari.

Per esempio:

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; 

che troverete in questa unità molto più di un semplice collegamento statico di SQLite3. Si noti che anche se è utilizzato dal nostro framework client-server mORMot ORM, questo ORM è non necessario per utilizzare le classi SQLite3. Vedi this article for additional details.

Se ci si perde nel nostro repository del codice sorgente (utilizzando il grande progetto FOSSIL), read this.

+0

+1 Molto meglio usare il codice esistente dove si adatta bene. –

+0

Alla fine ho finito con la ricompilazione del file versione 3.7.9 di sqlite3.c me stesso e la sostituzione del file 3.7.8 sqlite3.obj in SynSQLite3. Ciò ha reso l'esecuzione uguale alla versione 2.4 di DISQlite3. Screenshot con la profilazione allegata alla domanda. –

+0

I file sqlite3.obj forniti nella versione corrente sono già in 3.7.9. Vedi [il link che ho fornito] (http://synopse.info/fossil/wiki?name=Get+the+source) alla fine della mia risposta. Download diretto [da qui] (http://synopse.info/files/sqlite3obj.7z). Questa è la versione istantanea - la versione ufficiale 1.15 utilizza ancora la 3.7.8. Grazie mille per il tuo interesse su Open Source! Sei il benvenuto nei nostri forum se vuoi unirti al progetto e impegnare del codice per migliorare l'unità. –

4

Aggiornamento: Sarete molto meglio con SynSQLite3.pas come suggerito da Arnaud. Tuttavia, sto lasciando questa risposta qui poiché illustra alcuni dei trucchi che possono essere utilizzati per risolvere le dipendenze mancanti durante il collegamento statico.


Quello che sta accadendo qui è che il file obj dipende dalle funzioni di runtime C che devono essere fornite da voi.

La prima cosa da fare è aggiungere crtl alla clausola uses che contiene la direttiva $LINK. L'unità crtl contiene implementazioni di un numero delle funzioni della libreria di runtime C ed è progettata proprio per questo scopo.

Tuttavia, quando si esegue questa operazione, mentre alcune dipendenze mancanti vengono risolte, ne appaiono molte altre.

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' 

Molti di questi sono semplicemente funzioni API di Windows e può essere facilmente risolto con l'aggiunta di Windows alla clausola uses.

A questo punto si sono lasciati con la seguente:

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' 

Per risolvere questi è necessario uno:

  1. link un altro file obj contenente la dipendenza mancante.
  2. Implementare la dipendenza mancante nel codice Delphi nella stessa unità che contiene lo $LINK.

In realtà non sono sicuro di cosa facciano queste funzioni, quindi hai un po 'più di lavoro davanti a te. La mia ipotesi è che queste funzioni sono routine aritmetiche a 64 bit interi. Probabilmente è possibile decodificare questo processo scrivendo brevi bit di C per eseguire varie operazioni aritmetiche a 64 bit. Quindi compilare con bcc32 e osservare l'output come asm. Presumibilmente bcc32 ha la capacità di emettere asm. Oppure potresti semplicemente collegarti a un'unità Delphi e vedere quale delle funzioni sopra indicate corrisponde alle operazioni che hai usato nel tuo codice C.

È possibile estrarre localtime su msvcrt.dll, sempre un'opzione di fallback utile per le funzioni di runtime C mancanti. In effetti, questo è ciò che fa l'attuale implementazione dell'unità crtl, quindi se hai intenzione di usare crtl puoi anche ottenere localtime allo stesso modo.


Prendendo in prestito un po 'di codice Arnaud, la seguente unità compilato correttamente:

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. 

Si noti che non è necessario fornire l'elenco dei parametri, convenzione di chiamata ecc per qualsiasi di queste funzioni dal momento che siamo non li stiamo implementando qui. In ogni caso il codice semplicemente delega l'implementazione.

Tuttavia, manca ancora il codice per dichiarare le funzioni sqlite3. Inoltre, non ho nemmeno provato a verificare se funziona o meno. La compilazione riuscita è solo il primo passo.

Si consiglia vivamente di utilizzare il codice indicato da Arnaud se si desidera utilizzare il collegamento statico. Questo codice ha chiaramente avuto molto uso e test e potrebbe anche trarne beneficio.


linking statico rende conveniente distribuzione, ma il collegamento dinamico contro una DLL è molto più semplice da raggiungere.

+0

Queste funzioni sono helper per numeri interi a 64 bit (firmati e "u" nsigned).Sui sistemi gcc tali funzioni sono in libgcc. Potrebbe essere necessario collegare staticamente da un file oggetto msvc. –

+0

È possibile che sia stato downvoted instrad di upvoted la risposta per errore. Se fossi stato io per favore fatemi sapere per correggere. Se non ero io, cancella questo commento. –

+1

Una piccola unità di crtl di osservazione è disponibile con il nome System.Win.Crtl.pas in Delphi XE2 ed è disponibile con il codice sorgente anche in C: \ Programmi \ Embarcadero \ RAD Studio \ 9.0 \ source \ rtl \ common se l'impostazione predefinita viene utilizzato il percorso di installazione. Nella versione precedente di XE era disponibile solo come crtl.dcu. –

Problemi correlati