質問

C ++のアンマネージDLLに関するチュートリアル/記事をたくさん読んでいます。しかし、私の人生では、この概念を把握することはできません。ヘッダーファイルが必要かどうか、それをエクスポートする方法、.libファイルが必要かどうか、何が必要かについての意見の不一致に、私は簡単に混乱しています。

だから、私はそのような関数だけを持っていると仮定しましょう:

public int calculateSquare(int num)
{
    return num*num;
}

実際のコードを無視して、この単純な関数を単独でDLLにして、それを呼び出し可能にするために必要なものは何ですか? __dllexportなどを最初の行に追加するだけですか、それともヘッダーが必要ですか?私はこのすべてに困惑しています。

役に立ちましたか?

解決

これを十分に強調することはできません。C++コンパイラはヘッダーファイルを表示しません。プリプロセッサの実行後、1つの大きなソースファイル(コンパイル単位とも呼ばれます)があります。したがって、厳密には、dllからこの関数をエクスポートするためのヘッダーは必要ありません。 必要なのは、コンパイルしているdll内の関数をエクスポートし、クライアントコードにインポートするための条件付きコンパイルの形式です。

通常、これはマクロとヘッダーファイルの組み合わせで行われます。 MYIMPORTEXPORTというマクロを作成し、マクロ条件ステートメントを使用して、dllで__declspec(dllexport)、クライアントコードで__declspec(dllimport)のように動作させます。

MYMYPORTEXPORT.hファイル内

#ifdef SOME_CONDITION
#define MYIMPORTEXPORT __declspec( dllexport )
#else
#define MYIMPORTEXPORT __declspec( dllimport )
#endif

MyHeader.hファイル内

#include <MyImportExport.h>

MYIMPORTEXPORT public int calculateSquare(int num)
{
    return num*num;
}

dll .cppファイル内

#define SOME_CONDITION

#include <MyHeader.h>

クライアントコード.cppファイル内

#include <MyHeader.h>

もちろん、 / DLLオプション

ビルドプロセスも.libファイルを作成します。これは、この場合スタブと呼ばれる静的ライブラリです。クライアントコードは、実際の静的ライブラリにリンクするかのようにリンクする必要があります。自動的に、クライアントコードの実行時にdllがロードされます。もちろん、dllはその検索メカニズムを介してOSによって検出される必要があります。つまり、dllを特定の場所以外の場所に置くことはできません。 こちらはその詳細です。

dllから正しい関数をエクスポートしたかどうか、およびクライアントコードが正しくインポートされているかどうかを確認するための非常に便利なツールは、 dumpbin 。 / EXPORTSおよび/ IMPORTSでそれぞれ実行します。

他のヒント

QBziZの答えで十分です。 C ++のアンマネージDLL

をご覧ください。

それを完了するには: C ++では、シンボルを使用する必要がある場合、コンパイラーに存在すること、そしてしばしばそのプロトタイプを伝える必要があります

他の言語では、コンパイラはそれ自体でライブラリを探索し、シンボル et voil&#224; を見つけます。

C ++では、コンパイラーに伝える必要があります。

C / C ++ヘッダーを目次として見る

最良の方法は、必要なコードを一般的な場所に置くことです。必要に応じて、「インターフェイス」。これは通常、独立したソースファイルではないため、headerと呼ばれるヘッダーファイルで行われます。ヘッダーは、目的が真のソースファイルに含まれる(つまり、プリプロセッサによってコピー/貼り付けされる)ファイルのみです。

実質的に、シンボル(関数、クラスなど)を2回宣言する必要があるようです。他の言語と比較すると、これはほとんど異端です。

概要表または索引付きの本として表示されるはずです。表には、すべての章があります。本文には、章とその内容があります。

そして時々、あなたはチャプタリストを持っているだけで幸せです。

C ++では、これはヘッダーです。

DLLはどうですか?

では、DLLの問題に戻ります。DLLの目的は、コードが使用するシンボルをエクスポートすることです。

したがって、C ++の方法では、コンパイル時にコードをエクスポートする必要があります(つまり、Windowsでは、たとえば__declspecを使用します)および&quot; publish&quot;エクスポートされたもののテーブル(つまり、エクスポートされた宣言を含む&quot; public&quot;ヘッダーがあります)。

関数をエクスポートするためのチェックリスト:

  • 呼び出し元に適した呼び出し規約はありますか? (これにより、パラメーターと結果の受け渡し方法、およびスタックのクリーンアップの責任者が決まります)。呼び出し規約を明示的に記述してください。
  • シンボルをエクスポートする名前の下で? C ++は通常、シンボルの名前を修飾(「マングル」)する必要があります。異なるオーバーロードを区別するため。
  • リンカーに関数をDLLエクスポートとして表示するよう指示する

MSVCの場合:

  • __ stdcall (pascal呼び出し規則)は、エクスポートされたシンボルの典型的な呼び出し規則です-私が推測するほとんどのクライアントでサポートされています。
  • extern&quot; C&quot;名前マングリングなしでシンボルCスタイルをエクスポートできます
  • __ declspec(dllexport)を使用して、エクスポートするシンボルをマークするか、エクスポートするシンボルがリストされている別の.defファイルをリンクします。 .defファイルを使用すると、(名前ではなく)序数のみでエクスポートし、エクスポートされるシンボルの名前を変更することもできます。

__ declspec(dllexport)を使用して関数をエクスポートするか、モジュール定義ファイル(.def)に関数を追加する必要があります。次に、thoプロジェクトをDLLとしてコンパイルします。

クライアント側には、2つのオプションがあります。 DLLのコンパイル時に生成されるインポートライブラリ(.lib)を使用します。このライブラリを使用してクライアントプロジェクトとリンクするだけで、DLLからエクスポートされた関数にアクセスできます。また、コンパイラは関数のシグネチャを知る必要があるため、ヘッダーファイルが必要です。これは、intを返し、intを取得するということです。要約すると、インポートライブラリ(.lib)および関数のヘッダーを含むヘッダーファイルとリンクする必要があります。

別の方法は、 WinAPI 呼び出し LoadLibrary を使用してDLLを動的にロードし、次に GetProcAddress を使用して関数へのポインターを取得することです。関数へのポインタは正しい型を持たなければならないので、コンパイラはそれに正しいパラメータを与えることができ、正しい呼び出し規約が使用されます。

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