Come utilizzare Crtl in un'unità di Delphi in un progetto di C ++ Builder? (O link alla libreria di runtime C ++ Builder C)

StackOverflow https://stackoverflow.com/questions/5303568

  •  24-10-2019
  •  | 
  •  

Domanda

Ho un'unità di Delphi, che è il collegamento in modo statico file obj un C utilizzando la direttiva {$L xxx}. Il file C viene compilato con la linea di comando del compilatore di C ++ Builder. Per soddisfare le dipendenze delle librerie di runtime del file C (_assert, memmove, ecc), sto tra cui l'unità crtl Allen Bauer menzionato qui .

unit FooWrapper;

interface

implementation

uses
 Crtl; // Part of the Delphi RTL

{$L FooLib.obj}  // Compiled with "bcc32 -q -c foolib.c"

procedure Foo; cdecl; external;

end.

Se io compilo tale unità in un progetto Delphi (.dproj) Everthing correttamente lavori.

Se io compilo tale unità in un progetto di C ++ Builder (.cbproj) non riesce con l'errore:

[ILINK32 Error] Fatal: Unable to open file 'CRTL.OBJ'

E, in effetti, non v'è un file crtl.obj nel RAD Studio cartella di installazione. C'è un .dcu, ma non .pas. Cercando di aggiungere crtdbg alla clausola uses (l'intestazione C dove _assert è definito) dà un errore che non può trovare crtdbg.dcu.

Se rimuovo i usi clausola, invece fallisce con errori che __assert e _memmove non si trovano.

Così, in un'unità di Delphi in un progetto di C ++ Builder, come posso esportare le funzioni dalla libreria di runtime C in modo che siano disponibili per il collegamento?

Sono già a conoscenza di Rudy Velthuis articolo . Mi piacerebbe evitare di scrivere manualmente wrapper Delphi, se possibile, dal momento che io non li ho bisogno in Delphi e C ++ Builder deve già includere le funzioni necessarie.

Modifica

Per chi vuole giocare insieme a casa, il codice è disponibile nel repository Subversion di Abbrevia all'indirizzo https://tpabbrevia.svn.sourceforge.net/svnroot/tpabbrevia/trunk . Ho preso il consiglio di David Heffernan e aggiunto un'unità "AbCrtl.pas" che imita crtl.dcu quando viene compilato in C ++ Builder. Che ha ottenuto il lavoro di supporto PPMd, ma le librerie LZMA e WavPack entrambi falliscono con errori di collegamento:

[ILINK32 Error] Error: Unresolved external '_beginthreadex' referenced from ABLZMA.OBJ
[ILINK32 Error] Error: Unresolved external 'sprintf' referenced from ABWAVPACK.OBJ
[ILINK32 Error] Error: Unresolved external 'strncmp' referenced from ABWAVPACK.OBJ
[ILINK32 Error] Error: Unresolved external '_ftol' referenced from ABWAVPACK.OBJ

AFAICT, tutti loro sono dichiarati in modo corretto, e il _beginthreadex uno è in realtà dichiarato nel AbLzma.pas, quindi è utilizzato dalla compilazione puro Delphi pure.

Per vedere da soli, basta scaricare il tronco (o semplicemente la "fonte" e "pacchetti" directory), disabilitare il blocco {$ IFDEF BCB} in fondo AbDefine.inc, e cercare di compilare il C ++ Builder progetto "Abbrevia.cbproj".

È stato utile?

Soluzione

Il mio prendere su questo è che è necessario solo l'unità di Delphi nella versione di Delphi del progetto.

Nella versione Builder C ++ è sufficiente compilare e linkare foolib.c come se fosse un file C (è!) Nella versione di Delphi del programma si crea l'obj con bcc32, utilizzare CTRL ecc come descritto.

Perché vuoi per avvolgere in su una libreria C in un involucro Delphi per essere consumato in C ++?

Modifica 1

Hai chiarimenti aggiunto nei commenti.

Un'altra opzione da considerare sarebbe quella di evitare Crtl e implementare le funzioni mancanti in FooWrapper. Lo faccio in questo modo piuttosto che usare crtl perché questo mi dà più controllo e capisco ciò che viene chiamato. Per esempio, io non voglio nessuna chiamata a printf() che perde nel mio app GUI o la mia DLL.

Questa potrebbe essere un'opzione interessante se si è solo manca una manciata di funzioni. Spesso il modo più grazioso per farli è di collegarli in da msvcrt.dll che è un componente di sistema standard di questi giorni. Certo che sembra un po 'pesante per collegamento in msvcrt.dll solo per arrivare a memset(), memcpy() etc.

Quanti funzioni mancanti sono lì quando si compila l'unità Delphi senza Crtl?

Modifica 2

Sto aggiungendo questo per la risposta a mostrare un po 'di codice. Dalla mia base di codice offro questo:

const
  __turboFloat: Longint=0;
  (* We don't actually know the type but it is 4 bytes long and initialised to zero.  This can be determined
     using tdump initcvt.obj.  It doesn't actually matter how we define this since it is ultimately not
     referred to and is stripped from the executable by the linker. *)

Per link che ho ftol in ftol.obj che presumo ho estratto da uno dei file lib del compilatore BCC55 che uso.

Credo strncmp dovrebbe essere abbastanza di routine da implementare in pianura Pascal.

sprintf è più difficile in piena generalità, ma si potrebbe scoprire che è utilizzato solo per qualcosa di banale come numero intero a stringa. Nel qual caso si potrebbe fudge il codice C per chiamare una routine dedicata per questo e attuarlo banalmente.

Per essere onesto con te, penso che 'Msvcrt.dll' sembra piuttosto interessante!

EDIT 3

Ti parlo troppo presto? Si può tirare un sprintf fuori perfettamente funzionale di user32.dll, che quasi tutti i processi hanno caricato in ogni caso. Assicuratevi di scegliere wsprintfA se si tratta di un versione ANSI è necessario.

Modifica 4

I preavviso _beginthreadex. Tu dici che questo è definito in un'unità di Delphi diverso. Al fine di ottenere il compilatore per vederlo è necessario ridichiarare in AbCtrl.pas e da lì chiama la versione reale di AbLzma.pas.

Quando si include un .obj in un file Delphi .pas il compilatore deve essere in grado di risolvere tutti i riferimenti nel file obj dall'interno l'unità di Delphi, che collegamenti al obj. intero Questo gioco è trattata dal compilatore, piuttosto che linker.

A volte si impigliarsi in nodi con l'ordine in cui si includono i file obj e la soluzione è quella di utilizzare le dichiarazioni in avanti, ma questa è un'altra storia.

Altri suggerimenti

In questo caso, le funzioni a cui sei interessato si presume che siano disponibili direttamente dalla C RTL, in modo da falsificare il linker con un manichino (vuoto) obj file dovrebbe funzionare come in grado di soddisfare il linker che cerca il file obj che Delphi ha detto che è necessario, ma ancora trovare le funzioni in RTL.

ritardo, ma più completo: crtl.dcu funziona senza problemi dal D2005 fino al XE2.

Per D6 e D7 v'è una dipendenza da midaslib.dcu. Beh, non proprio, il DCU è distribuito con una clausola usi sporchi.

Per D6 e D7 si dovrebbe creare un midaslib.pas VUOTO surrogati, come:

unit midaslib;
interface
implementation
end.

Ora è possibile utilizzare crtl.dcu senza gli errori interni!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top