[解決済み] dllexport を使って DLL から関数をエクスポートする
質問
C++のWindows DLLから関数をエクスポートする簡単な例が知りたいです。
私は、ヘッダ、つまり
.cpp
ファイル、そして
.def
ファイル (絶対に必要な場合) を追加します。
エクスポートされる名前を
装飾なし
. 最も標準的な呼び方である (
__stdcall
?). を使いたいのですが
__declspec(dllexport)
を使う必要がなく
.def
ファイルを使用する必要がありません。
例えば
//header
extern "C"
{
__declspec(dllexport) int __stdcall foo(long bar);
}
//cpp
int __stdcall foo(long bar)
{
return 0;
}
リンカがアンダースコアや数字(バイト数?)を名前に付加してしまうのを避けるためです。
をサポートしないのはOKなんだけど
dllimport
と
dllexport
を同じヘッダを使用しています。C++のクラスメソッドのエクスポートに関する情報は必要なく、cスタイルのグローバル関数だけでいいのです。
アップデイト
呼び出しの規約を含めず(そして
extern "C"
を使用) は、私が望むようなエクスポート名を与えますが、これは何を意味するのでしょうか? 私が取得したデフォルトの呼び出し規約は、pinvoke(.NET)、declare(vb6)、および
GetProcAddress
が期待するものなのでしょうか?(私は
GetProcAddress
については、呼び出し元が作成した関数ポインタに依存すると思います)。
私はこのDLLをヘッダーファイルなしで使用したいので、多くの派手な
#defines
のような、呼び出し側でヘッダを使用できるようにするための多くの派手なものは必要ありません。
を使わなければならないという答えでOKです。
*.def
ファイルを作成することです。
どのように解決するのですか?
プレーンな C エクスポートが必要な場合、C++ ではなく C プロジェクトを使用します。C++ DLL は、すべての C++ イズム (名前空間など...) のために名前マングリングに依存しています。プロジェクト設定の C/C++->Advanced に、コンパイラー スイッチの /TP と /TC に対応する "Compile As" というオプションがあるので、コードを C としてコンパイルすることができます。
lib の内部を記述するのに C++ を使用し、C++ の外部で使用するためにいくつかの関数をアンマングルでエクスポートしたい場合、以下の 2 番目のセクションを参照してください。
VC++ での DLL リブのエクスポート/インポート
本当にやりたいことは、DLL プロジェクト内のすべてのソースファイルに含まれるヘッダーで条件付きマクロを定義することです。
#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif
そして、エクスポートさせたい関数で
LIBRARY_API
:
LIBRARY_API int GetCoolInteger();
ライブラリビルドプロジェクトで
LIBRARY_EXPORTS
これにより、DLLビルドのために関数がエクスポートされます。
ということは
LIBRARY_EXPORTS
はDLLを消費するプロジェクトでは定義されないので、そのプロジェクトがライブラリのヘッダファイルを含むとき、すべての関数が代わりにインポートされます。
ライブラリがクロスプラットフォームである場合、Windows 以外では LIBRARY_API を何も定義しないようにすることができます。
#ifdef _WIN32
# ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
# else
# define LIBRARY_API __declspec(dllimport)
# endif
#elif
# define LIBRARY_API
#endif
dllexport/dllimport を使用する場合、DEF ファイルを使用する必要はなく、DEF ファイルを使用する場合、dllexport/dllimport を使用する必要はありません。 2 つの方法は同じタスクを異なる方法で達成しますが、2 つの方法のうち dllexport/dllimport が推奨される方法であると私は信じています。
LoadLibrary/PInvoke 用の C++ DLL からマングルされていない関数をエクスポートする
LoadLibraryやGetProcAddressを使用したり、他の言語(.NETのPInvokeやPython/RのFFIなど)からインポートする必要がある場合、以下のように使用できます。
extern "C"
を使用して、C++コンパイラに名前を混乱させないように指示することができます。 また、dllimport の代わりに GetProcAddress を使用しているため、上記の ifdef ダンスは必要なく、単純な dllexport を使用するだけです。
コードです。
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
EXTERN_DLL_EXPORT int getEngineVersion() {
return 1;
}
EXTERN_DLL_EXPORT void registerPlugin(Kernel &K) {
K.getGraphicsServer().addGraphicsDriver(
auto_ptr<GraphicsServer::GraphicsDriver>(new OpenGLGraphicsDriver())
);
}
そして、Dumpbin /exportsでエクスポートするとこんな感じです。
Dump of file opengl_plugin.dll
File Type: DLL
Section contains the following exports for opengl_plugin.dll
00000000 characteristics
49866068 time date stamp Sun Feb 01 19:54:32 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 0001110E getEngineVersion = @ILT+265(_getEngineVersion)
2 1 00011028 registerPlugin = @ILT+35(_registerPlugin)
というわけで、このコードは問題なく動作します。
m_hDLL = ::LoadLibrary(T"opengl_plugin.dll");
m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(
::GetProcAddress(m_hDLL, "getEngineVersion")
);
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(
::GetProcAddress(m_hDLL, "registerPlugin")
);
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ハートビート・エフェクトのためのHTML+CSS
-
HTML ホテル フォームによるフィルタリング
-
HTML+cssのボックスモデル例(円、半円など)「border-radius」使いやすい
-
HTMLテーブルのテーブル分割とマージ(colspan, rowspan)
-
ランダム・ネームドロッパーを実装するためのhtmlサンプルコード
-
Html階層型ボックスシャドウ効果サンプルコード
-
QQの一時的なダイアログボックスをポップアップし、友人を追加せずにオンラインで話す効果を達成する方法
-
sublime / vscodeショートカットHTMLコード生成の実装
-
HTMLページを縮小した後にスクロールバーを表示するサンプルコード
-
html のリストボックス、テキストフィールド、ファイルフィールドのコード例