静的ライブラリにリソースを構築し、ライブラリとリンクするだけでそれらを再利用することは可能ですか?
私は主に、ライブラリ内の関数を呼び出して、リソースにアクセスする場合について考えています。
静的ライブラリにリソースを構築し、ライブラリとリンクするだけでそれらを再利用することは可能ですか?
私は主に、ライブラリ内の関数を呼び出して、リソースにアクセスする場合について考えています。
Visual C++ (2008) のスタティック ライブラリでリソース (画像、ダイアログなど) を使用するために必要な唯一のことは、プロジェクトにスタティック ライブラリの関連する .res ファイルを含めることです。これは、「プロジェクト設定/リンカー/入力/追加の依存関係」で行うことができます。
このソリューションでは、スタティック ライブラリのリソースが .exe にパックされるため、追加の DLL は必要ありません。残念ながら、Visual Studio は .lib ファイルの場合のように .res ファイルを自動的にインクルードしませんが (「プロジェクトの依存関係」機能を使用する場合)、この小さな追加ステップは許容できると思います。
私はこのソリューションを非常に長い間探してきましたが、今では驚くほど簡単です。唯一の問題は、それが完全に文書化されていないことです。
それはできますが、かなり面倒です。単に静的ライブラリとリンクするだけではできません。
これを考慮してください。リソースは EXE または DLL に埋め込まれています。スタティック ライブラリの一部のコードが (例: LoadIcon) を呼び出すと、リンクされている EXE または DLL からリソースを取得します。
そのため、静的ライブラリでリソースを利用できるようにする必要がある場合は、いくつかのオプションがあります。
CreateDialogIndirect
。Raymond Chen の「実行時にダイアログ テンプレートを構築する」を参照してください。char my_dialog_resource[] = { .... };
(eg) を使用できますCreateDialogIndirect
。.RES
おそらく、ファイルからファイルに変換するユーティリティを見つける (または作成する) 必要があり.CPP
ます。.RC
ファイル) と対応するヘッダー ファイルを含む LIB ファイルを出荷できます。次に#include
、関連するものとしてそれらを選択します。LIB が使用するリソース ID の範囲を予約して、メインの EXE または DLL のリソース ID と競合しないようにする必要があります。これは、MFC がスタティック ライブラリとして使用される場合の動作です。または、文字列のリソース ID を使用できます (これはリソースには機能しませんSTRINGTABLE
)。私はMSVisualStudioコンパイラでこれを実行しました。いくつかのレガシープロジェクトをDLLから静的ライブラリに変換していました。これらのDLLのいくつかには、ダイアログまたは文字列リソースが埋め込まれていました。これらのDLLの.RCスクリプトを、「TEXTINCLUDE」メカニズムを介してメインアプリケーションのRCスクリプトファイルに含めることにより、メインアプリケーションにコンパイルすることができました。RCファイルを直接編集するのが最も簡単だと思いましたが、VisualStudioにはもう少し「奇妙な」メカニズムも用意されています。他のコンパイラでは、実装が異なる可能性があります。
メインRCスクリプトを直接操作するには:
.1。「2TEXTINCLUDE」セクションに、ライブラリのリソースIDを定義するヘッダーファイルをインクルードします。構文は
2 TEXTINCLUDE
BEGIN
"#include ""my_first_lib_header.h""\r\n"
"#include ""my_second_lib_header.h""\0"
END
.2。「3TEXTINCLUDE」セクションに、ライブラリのRCスクリプトを含めます。
3 TEXTINCLUDE
BEGIN
"#include ""my_first_library.rc""\r\n"
"#include ""my_second_library.rc""\0"
END
手順3と4は自動的に実行されるはずですが、Microsoftのリソーススクリプトコンパイラに依存して処理するよりも、自分で入力する方が信頼性が高いことがわかりました。
.3。ライブラリリソース定義を含むヘッダーファイルを読み取り専用シンボルリストに追加します。このリストは通常、ファイルの先頭近くにあります。
#define APSTUDIO_READONLY_SYMBOLS
#include "my_first_lib_header.h"
#include "my_second_lib_header.h"
#undef APSTUDIO_READONLY_SYMBOLS
.4。ライブラリのRCスクリプトをAPSTUDIO_INVOKEDセクションに含めます。これは通常、ファイルの下部にあります。
#ifndef APSTUDIO_INVOKED
#include "my_first_library.rc"
#include "my_second_library.rc"
#endif
Visual Studio IDEを使用してこれらすべてを自動的に実行することもできますが、期待したときに常に適用されるとは限りませんでした。
ライブラリのリソーススクリプトがディスク上のファイル(テキストファイル、アイコンファイルなど)を参照している場合は、メインアプリケーションプロジェクトがそれらのファイルの場所を認識していることを確認する必要があります。これらのファイルをアプリケーションが見つけられる場所にコピーするか、コンパイラ設定に追加のインクルードパスを追加することができます。
インクルードパスを追加するには:
Visual Studio 2010 によると、Microsoft の開発ツールは、静的ライブラリ内のコンパイル済みリソース データを適切に処理できないようです。
コンパイル済みのリソース ファイル (.res
ファイル) を配布するには、次の 2 つの選択肢があります。
.res
それらに対してリンクするようにクライアント コードに指示します。cvtres
にマージし、個別に提供するために使用します。.res
.obj
で作成されたオブジェクト ファイルでは lib できないことに注意してくださいcvtres
。複数のオブジェクト ファイルが指定されている場合、複数のファイルが指定さlib
れているかのように文句を言います。.res
単一のオブジェクト ファイルが提供されている場合、エラーはlib
発生しませんが、リンカは単に lib ファイルに埋め込まれたリソース データを無視します。
リソースデータは実際にライブラリで利用可能であるため(コマンドラインオプション、セクション操作などを使用して)、リンカにリソースデータのlibbedを読み取らせてリンクさせる方法がある場合があります(dumpbin
明らかにする)。これまでのところ、私は解決策を見つけていません。また、開発ツールをハッキングする意思がない限り、この単純な解決策よりも優れたものは、おそらく努力する価値はありません。
静的ライブラリ (この場合は静的ライブラリ) でリソース データを出荷する唯一の方法は、リソースを個別に配布し、クライアント コードで明示的にリンクすることです。を使用cvtres
すると、分散リソース ファイルが多数ある場合に、その数を 1 つに減らすことができます。
私はそうは思わない。静的ライブラリには、独自のHINSTANCEがありません。そのコードは、それをリンクするDLLまたはEXEのコンテキストで実行されます。そのため、静的ライブラリのコードからロードしようとするすべてのリソースは、DLL/EXEを囲むリソースになります。
ただし、DLLが独自のアドレス空間を持っている限り、そのようなリソースをDLLで再利用しました。また、DLLのHINSTANCEを使用してLoadResourceを呼び出すことができます。
推奨される方法は、ライブラリと一緒にリソースを含む dll を提供することです。