web-dev-qa-db-ja.com

静的ライブラリをDLLとリンクする適切な方法

私のプロジェクトは、メインDLLライブラリにリンクする必要があるいくつかの静的ライブラリを介してビルドされ、結果として1つのDLLを取得します。

__declspec(dllexport)属性を使用しても、静的ライブラリの指定された関数がdllに表示されず、ライブラリはdllにまったくリンクされていません。

次に、エクスポートされた関数の適切な名前を取得するために共有として各ライブラリをビルドし、それらに基づいて.defファイルを作成しました。 .defファイルを使用すると、結果につながりました。

  1. __declspec(dllexport)および.def-file私の場合も同様に行動しますか?

  2. ソースから.defファイルを生成することは可能ですか?私はC++コードを持っているので、APIのマングリングとプレゼンスクラスのために.defファイルを自分で書き込むことができません。一時的に生成されたdllを使用する上記のアプローチは、本番環境では一貫性がありません。

更新

プロジェクトの構造について詳しく説明したいと思います。ソリューションは、いくつかのプロジェクト(モジュール)で構成されています。

+ 
|    
+-+ static_lib1                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ static_lib2                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ dynamic_lib (linked with static_lib1 and static_lib2)
        +                                                
        +--+ src

各サブプロジェクトは他のプロジェクトに弱く依存しています。明確にするために接続されていないと仮定しましょう。各モジュールには独自のパブリックインターフェイスがあります。すべてのモジュールを単一の動的ライブラリーにしたいので、アーティファクトはdynamic_lib.dll、しかし実際には静的ライブラリはそれにリンクされていません。

14
triclosan

静的ライブラリには、___declspec_または__attribute((dll...))のものが含まれていてはなりません。これらは、1つの単一ファイルに構成された複数のオブジェクトファイル(通常は_*.obj_または_*.o_)にすぎません。

このようなライブラリ(_.exe_または_.dll_のいずれか)を使用するために必要なことは、適切なヘッダーを含めてリンクすることだけです。VisualStudioを使用すると、非常に簡単です。

まず、静的ライブラリが配置されている場所1)および正確な名前2)を知る必要があります。プロジェクトのプロパティに移動し、次にGeneralに移動します。 _Target name_には出力ファイルの名前が含まれ、_Output directory_は_.lib_がどのフォルダーに配置されるかを示します。

注:このパスはプロジェクトごとに異なる場合があります!マルチプロジェクトソリューションでは、構成の問題を回避するために、これを常に共通のパスに設定します。

次に、プロジェクトのプロパティに移動します。これにより、このライブラリが使用されます(リンクされます)。 Linker-> Inputに移動し、_.lib_の名前を_Additional dependencies_に追加します(エントリはセミコロンで区切られます):

Linker input

リンクしたいすべてのライブラリーを追加する必要があります。また、これらのライブラリーが配置されているフォルダーをLinker-> General-> _Additional library directories_に追加する必要があります。すべての_.lib_ sが同じ場所に配置されている場合-良い、それ以外の場合はそれらを共有の場所にコピーするか、_Additional library directories_リストに複数のエントリを追加します。

そして最後に、使用したい関数とオブジェクトの宣言を含むヘッダーも含める必要があることを覚えておいてください。基本的なことはわかっていますが、言及する必要があります。


[〜#〜]更新[〜#〜]

外部プロジェクトでdllライブラリを使用しようとすると、未解決の外部

あなたの問題はnotリンクに関連しています。問題は、静的ライブラリをリンクすることで誤解していることです正確に

unresolvedとして報告された関数は、あなたのDLLによって使用されていないと思いますか?しかし、あなたは彼らがその中にいると期待していますよね?

DLLが外部のコンテンツ(関数や変数など)を参照する場合、リンク時にすべての依存関係とともに解決されます。 しかしそれだけです。静的ライブラリにprint_sample_string()という名前の関数がある場合ただし、DLLはそれを使用しませんDLL画像にアタッチされません。これについて慎重に考えてください。なぜそうすべきなのでしょうか。

さらに-dllexportedされていない関数は明示的に表示されません。関数にはデフォルトで外部ストレージがあります-したがって、基本的に、それらはプライベートDLLのコンテンツです。

したがって、質問に直接回答するには、_static_lib1.lib_の関数/変数を使用する必要がある場合は、クライアントアプリケーションにアタッチします。これは、_dynamic_lib_にアタッチするのと同じです。他に方法はありません。 (*)


(*)本当に言えば-あります。 DLLに中間関数を作成し、それをエクスポートして、内部で必要な関数を呼び出すことができます。

_dynamic_lib_:のどこかに

_DLL_EXP_IMP long CallFunctionFromA_Lib()
{
     return some_function(); //this function is from static_lib1.lib
}
_

_.exe_:のどこかに

_long result = CallFunctionFromA_Lib(); //internally this will call function from static_lib1.lib
_

しかし、単純に_A.lib_をリンクして直接使用するのではなく、なぜこれを実行するのかは想像できません。

16
Mateusz Grzejek

ここ Raymond Chanがこの動作を説明しており、最善の解決策はdefファイルを使用することです。静的ライブラリの自動生成方法については、 this の議論が出発点のように見えます。

4
dewaffled