2012-05-09 9 views
4

モノリシックアプリケーションをモジュール化するために、リリースビルド用に単一のexeファイルにコンパイルしながら、デバッグビルドで使用するパッケージを設定しています。ランタイムパッケージを使用してビルド中に「インポートされたデータ参照が必要」を解決する方法

私たちのパッケージ(EAUtils)の1つに、現在[DCC Error] E2201 Need imported data reference ($G) to access 'SMsgDlgWarning' from unit 'SystemUtils'を生産しているユニットが含まれています。

これは、EAUtilsパッケージ自体をビルドするときに発生します。私はまだEAUtilsに依存するパッケージを作ることにはなっていません。 EAUtilsは、rtl/vclパッケージと、Jedi WinApiユニット用に作成したパッケージのみに依存します。

これは線の結果である:

// This is a TaskDialog override, with the same args as the old MessageDlg. 
function TaskDialog(const aContent: string; const Icon: HICON = 0; 
    const Buttons: TTaskDialogCommonButtonFlags = TDCBF_OK_BUTTON): Integer; 
const 
    Captions: array[TMsgDlgType] of Pointer = (@SMsgDlgWarning, @SMsgDlgError, @SMsgDlgInformation, @SMsgDlgConfirm, nil); 
var 
    aMsgDlgType: TMsgDlgType; 
    aTitle: string; 
begin 
    aMsgDlgType := TaskDialogIconToMsgDlgType(Icon); 
    if aMsgDlgType <> mtCustom then 
    aTitle := LoadResString(Captions[aMsgDlgType]) 
    else 
    aTitle := Application.Title; 

は、具体的にこれは全てVcl.Constで宣言されSMsgDlgWarningSMsgDlgErrorSMsgDlgInformationSMsgDlgConfirmを参照した結果です。

このコードは、単一の実行可能ファイルを作成する際にエラーなしでコンパイルされます。

最適化の手段として、私たちのインクルードファイルには{$IMPORTEDDATA OFF}が含まれています。これにより(グローバル)変数と定数への高速アクセスが可能になります。 http://hallvards.blogspot.com/2006/09/hack13-access-globals-faster.htmlを参照してください。

エラー(http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/cm_package_varref_xml.html)のドキュメントによると、これが原因で、「問題を緩和するには、通常、$ IMPORTEDDATAスイッチをオンにして、エラーを生成するユニットを再コンパイルするのが最も簡単です。

私はインクルードファイルに{$IMPORTEDDATA ON}を設定しており、プロジェクトオプションのDelphi Compiler | Compiling | DebuggingセクションにUse imported data referencesをtrueに設定することで二重に確認しました。

残念ながら、ドキュメントに反して、これは問題を緩和しませんでした。このコンパイラ指令を問題のコードの真上に設定してパッケージを再構築しても、エラーは削除されませんでした。

このE2201エラーを解決するには他に何が必要ですか? SMsgDlgWarningとそのフレンドがリソース文字列であることが重要なのでしょうか?

+1

パッケージをコンパイルするときにこのエラーが発生することがありますが、ビルドは常に機能します。 – jpfollenius

+0

@Smasher:ありがとう、私はビルドしました。条件付きの定義とあまりにも多くの手間がかかっていて、ちょうどコンパイルされているので、Shft-F9は私の指の中にあります。 –

+0

'$ IMPORTEDDATA'を付けたユニットを含む元のパッケージを再構築しても、依存するパッケージをビルドするときに結果の.dcuと.dcpを使用していることを確認してください。 –

答えて

8

エラーメッセージは、IMHOです。誤解を招く可能性があります。Vcl.Constsは、$G-でコンパイルされており、この問題が原因です。 (それがローカライズを壊すが)あまりにも、文字列のconstの配列は、コンパイル使用

function Captions(AType: TMsgDlgType): Pointer; 
begin 
    Result := nil; 

    case AType of 
    TMsgDlgType.mtWarning: 
     Result := @SMsgDlgWarning; 
    TMsgDlgType.mtError: 
     Result := @SMsgDlgError; 
    TMsgDlgType.mtInformation: 
     Result := @SMsgDlgInformation; 
    TMsgDlgType.mtConfirmation: 
     Result := @SMsgDlgConfirm; 
    end; 
end; 

const 
    Captions: array[TMsgDlgType] of string = (SMsgDlgWarning, SMsgDlgError, SMsgDlgInformation, SMsgDlgConfirm, ''); 

か、含む、独自のパッケージを構築することができ 回避策として、あなたはこのようなものを使用することができますVcl。*単位を{$G+}と置き換えて、標準のvclパッケージの代わりに使用してください。私は最初の解決策を好む。後者は潜在的に、後で展開(いわゆる「DLL地獄」)によって多くの問題を引き起こす可能性があります。

+0

ありがとうございました!私はローカルvarといくつかのキャストで試してみましたが、関数を使うことは考えていませんでした。 –

+0

ようこそ、ありがとう!また、 'const array of string'のケースも追加しました。 –

+0

他の場所で便利になるかもしれないので、面白く面白いです。私は元のresourcestringsのローカライゼーションに関してどのような効果があるのだろうと思います。私の推測では、const配列は、コンパイル時にresourcestringsの値で初期化され、現在の通常の文字列である項目は、リソースdllから変換された文字列に置き換えられず、どちらもLoadResStringに渡すことができません元のリソースレコードのアドレスで処理しています。 –

関連する問題