静的ライブラリにリソースを構築し、ライブラリとリンクするだけでそれらを再利用することは可能ですか?
私は主に、ライブラリ内の関数を呼び出してリソースにアクセスする場合について考えています。
それは可能ですが、それは非常に苦痛です。静的ライブラリとリンクするだけではそれを行うことはできません。
これを考慮してください。リソースはEXEまたはDLLに埋め込まれています。静的ライブラリ内の一部のコードが(たとえば)LoadIconを呼び出すと、EXEまたはリンク先のDLL)からリソースを取得します。
したがって、静的ライブラリでリソースを利用できるようにする必要がある場合は、いくつかのオプションがあります。
CreateDialogIndirect
を使用できます。 Raymond Chenの "実行時のダイアログテンプレートの作成" を参照してください。char my_dialog_resource[] = { .... };
としてライブラリに埋め込んでから、(たとえば)CreateDialogIndirect
を使用することができます。おそらく、.RES
ファイルから.CPP
ファイルに変換するユーティリティを見つける(または作成する)必要があります。.RC
ファイル)および対応するヘッダーファイルとともに出荷できます。次に、関連するものとして#include
します。 LIBが使用するリソースIDの範囲を予約して、メインのEXEまたはDLLのリソースIDと衝突しないようにする必要があります。これは、MFCが静的ライブラリとして使用されるときに行うことです。または、文字列リソースIDを使用できます(これはSTRINGTABLE
リソースには機能しません)。Visual C++(2008)の静的ライブラリでリソース(画像、ダイアログなど)を使用するために必要なのは、次のことだけです。 静的ライブラリに関連付けられた.resファイルを含める あなたのプロジェクトで。これは、「プロジェクト設定/リンカー/入力/追加の依存関係」で実行できます。
このソリューションでは、静的ライブラリのリソースが.exeにパックされるため、追加のDLLは必要ありません。残念ながら、Visual Studioには.libファイルの場合のように.resファイルが自動的に含まれません( "プロジェクトの依存関係"機能を使用する場合)が、この小さな追加の手順は許容できると思います。
私はこの解決策を非常に長い間探していましたが、今では驚くほど簡単です。唯一の問題は、完全に文書化されていないことです。
私はMSVisualStudioコンパイラでこれを実行しました。一部のレガシープロジェクトをDLLから静的ライブラリに変換していました。これらのDLLのいくつかには、ダイアログまたは文字列リソースが埋め込まれていました。これらのDLLの.RCスクリプトを「TEXTINCLUDE」メカニズムを介してメインアプリケーションのRCスクリプトファイルに含めることで、これらのDLLをメインアプリケーションにコンパイルすることができました。 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。 「3 TEXTINCLUDE」セクションに、ライブラリの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
)ファイルにマージし、個別に提供します。cvtres
で作成されたオブジェクトファイルをlibすることはできないことに注意してください。複数のオブジェクトファイルが提供されている場合、lib
は複数の.res
ファイルが指定されているかのように文句を言います。単一のオブジェクトファイルが提供されている場合、lib
は文句を言いませんが、リンカはlibファイルに埋め込まれたリソースデータを単に無視します。
リソースデータは実際にライブラリで利用可能であるため(コマンドラインオプション、セクション操作などを使用して)、リンカにリソースデータ内のlibbedを読み取ってリンクさせる方法がある場合があります( dumpbin
が明らかにします)。これまでのところ、解決策は見つかりませんでした。開発ツールをハックする意思がない限り、この単純な解決策よりも優れたものは、おそらく努力する価値がありません。
静的ライブラリ(この場合、with静的ライブラリ)でリソースデータを送信する唯一の方法は、リソースを個別に配布し、クライアントコードで明示的にリンクすることです。 cvtres
を使用すると、分散リソースファイルが多数ある場合に、それらの数を1つに減らすことができます。
私はそうは思いません。静的ライブラリには独自のHINSTANCEはありません。そのコードは、DLLまたはそれをリンクするEXEのコンテキストで実行されます。そのため、静的ライブラリのコードからロードしようとするすべてのリソースは、DLL/EXEを囲むものになります。
私はDLLを使用してそのようなリソースの再利用を行いましたが、独自のアドレス空間がある限り、DLLのHINSTANCEでLoadResourceを呼び出すことができます。
次の方法を使用すると、任意のリソース(この例ではアイコン)を静的ライブラリの不可欠な部分として使用でき、そのようなライブラリは、コンソールアプリケーション(を持たない)を含むすべてのタイプのアプリケーションで使用できます。任意のリソースセグメント)。
データはHICONハンドルに変換されます。これが私がそれをした方法です:
_HICON GetIcon()
{
DWORD dwTmp;
int offset;
HANDLE hFile;
HICON hIcon = NULL;
offset = LookupIconIdFromDirectoryEx(s_byIconData, TRUE, 0, 0, LR_DEFAULTCOLOR);
if (offset != 0)
{
hIcon = CreateIconFromResourceEx(s_byIconData + offset, 0, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
}
return hIcon;
}
_
LoadIconの代わりにGetIconが使用されます。呼び出す代わりに:
m_hIcon = ::LoadIcon(hInstanceIcon, MAKEINTRESOURCE(pXMB->nIcon));
次に、
_m_hIcon = GetIcon()
_
推奨される方法は、ライブラリと一緒にリソースをdllに提供することです。