C ++ビルダープロジェクトでDelphiユニットでCRTLを使用する方法は? (またはC ++ビルダーCランタイムライブラリへのリンク)

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

  •  24-10-2019
  •  | 
  •  

質問

を使用してC .OBJファイルを静的にリンクしているDelphiユニットがあります {$L xxx} 指令。 Cファイルは、C ++ビルダーのコマンドラインコンパイラでコンパイルされています。 Cファイルのランタイムライブラリの依存関係(_ASSERT、MEMMOVEなど)を満たすために、私は crtl ユニットアレンバウアーが言及した ここ.

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.

Delphiプロジェクト(.dproj)でそのユニットをコンパイルすると、Everthingが正しく機能します。

C ++ビルダープロジェクト(.cbproj)でそのユニットをコンパイルすると、エラーが失敗します。

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

そして確かに、ありません crtl.obj RADスタジオインストールフォルダーにファイル。 .dcuはありますが、.pasはありません。追加しようとしています crtdbg 使用句(_assertが定義されているCヘッダー)に、見つからないエラーが発生します crtdbg.dcu.

削除した場合 使用します 節、それはエラーで失敗します __assert_memmove 見つかりません。

それで、C ++ビルダープロジェクトのDelphiユニットでは、C Runtime Libraryから機能をエクスポートしてリンクできるようにするにはどうすればよいですか?

私はすでにルディ・ヴェルトゥイスのことを知っています 論文. 。 Delphiでそれらを必要としないので、可能であればDelphiラッパーを手動で書くことを避けたいと思います。C++ビルダーにはすでに必要な機能が含まれている必要があります。

編集

自宅で遊んでみたい人のために、コードはAbbreviaのSubversionリポジトリで利用できます https://tpabbrevia.svn.sourceforge.net/svnroot/tpabbrevia/trunk. 。 David Heffernanのアドバイスを受け取り、C ++ビルダーにコンパイルされたときにcrtl.dcuを模倣する「abcrtl.pas」ユニットを追加しました。これにより、PPMDサポートが機能しましたが、LZMAとWavpackライブラリはどちらもリンクエラーで失敗します。

[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

それらはすべて正しく宣言されており、_beginthreadexのものは実際にはablzma.pasで宣言されているため、純粋なDelphiコンパイルでも使用されます。

自分で確認するには、トランク(または「ソース」と「パッケージ」ディレクトリのみ)をダウンロードするだけで、abdefine.incの下部に{$ ifdef bcb}ブロックを無効にし、C ++ビルダー "abbreviaをコンパイルしてみてください.cbproj "プロジェクト。

役に立ちましたか?

解決

これについての私の考えは、プロジェクトのDelphiバージョンでDelphiユニットのみが必要だということです。

c ++ビルダーバージョンでは、qualib.cをコンパイルしてリンクするだけで、bcc32で.objを作成するプログラムのdelphiバージョンで、ctrlなどを使用するプログラムのdelphiバージョンのようにリンクします。

C ++で消費されるために、DelphiラッパーにCライブラリを締めくくりたいのですか?

編集1

コメントに説明を追加しました。

考慮すべき別のオプションは、CRTLを回避し、Foowrapperに欠落している関数を実装することです。 CRTLを使用するのではなく、私はそのようにします。なぜなら、それは私にもっとコントロールを与え、何が呼ばれているのかを理解しているからです。たとえば、私は電話をかけたくありません printf() GUIアプリまたはDLLに漏れています。

これは、ほんの一握りの関数しか欠けていない場合に魅力的なオプションかもしれません。多くの場合、それらを取得する最もきちんとした方法は、最近の標準システムコンポーネントであるMSVCRT.DLLからそれらをリンクすることです。もちろん、MSVCRT.DLLにリンクするだけで少し重いようです memset(), memcpy()

CRTLなしでDelphiユニットをコンパイルすると、欠落している機能がいくつありますか?

編集2

これを答えに追加して、いくつかのコードを表示しています。私自身のコードベースから私はこれを提供します:

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. *)

為に ftol FTOL.OBJにリンクします。これは、使用しているBCC55コンパイラのLIBファイルの1つから抽出したと思います。

おもう strncmp プレーンパスカルに実装するのにかなりルーチンである必要があります。

sprintf 完全な一般性はより困難ですが、整数のような些細なものにのみ使用されていることがわかります。その場合、Cコードをファッジして、その専用のルーチンを呼び出して、それを簡単に実装できます。

正直に言うと、「msvcrt.dll」はかなり魅力的に見えると思います!

編集3

すぐに話しましたか?完全に保守可能なものを引くことができます sprintf とにかくほとんどすべてのプロセスがロードされているuser32.dllから。必ず選択してください wsprintfA ANSIバージョンの場合は必要です。

編集4

私は気づく _beginthreadex. 。これは別のDelphiユニットで定義されていると言います。コンパイラにそれを確認させるには、abctrl.pasでそれを再作成する必要があり、そこからablzma.pasの実際のバージョンに電話してください。

delphi .pasファイルに.objを含めると、コンパイラは.objにリンクするDelphiユニット内から.objファイルのすべての参照を解決できる必要があります。このゲーム全体は、リンカーではなくコンパイラによって扱われます。

時々、.objファイルを含める順序で結び目が絡み合うことがあり、解決策はフォワード宣言を使用することですが、それは別の話です。

他のヒント

この場合、興味のある関数はC RTLから直接利用できると想定されているため、ダミー(空の)OBJファイルでリンカーを偽造することは機能するはずです。必要ですが、それでもRTLの関数を見つけます。

遅く、より完全な:CRTL.DCUは、D2005からXE2まで問題なく動作します。

D6およびD7の場合、Midaslib.dcuに依存しています。まあ、そうではありませんが、DCUは汚い使用条項で配布されています。

D6およびD7の場合、次のような空のmidaslib.pas surrogateを作成する必要があります。

unit midaslib;
interface
implementation
end.

これで、内部エラーなしでCRTL.DCUを使用できます!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top