Tips of VC++ > DLL > __declspec(dllexport)を使ってエクスポート
★ 前へ戻る ★ 次へ進む


このドキュメントにはサンプルプログラムが含まれています。
ワークスペース
ヘッダーファイル(テキスト)
ソースファイル(テキスト)


__declspec(dllexport)を使ってエクスポート

最初に「DLL概要」「エクスポートとインポートとリンク」を 読むと、すんなりと理解できるでしょう。
MSDNより引用しますが、説明はこれだけで十分です。 あとはサンプルを書いてみます。

__declspec(dllexport) キーワードを使うと、データ、関数、クラス、クラスのメンバ関数を DLL からエクスポートできます。__declspec(dllexport) を使う場合、エクスポート用の .DEF ファイルは不要です。

関数をエクスポートするには、呼び出し規約キーワードが指定されている場合、__declspec(dllexport) キーワードは呼び出し規約キーワードの左に記述します。以下に例を示します。

__declspec(dllexport) void __cdecl Function1(void);

クラス内のすべてのパブリック データ メンバおよびメンバ関数をエクスポートするには、__declspec(dllexport) キーワードは、以下のようにクラス名の左に記述します。

class __declspec(dllexport) CExampleExport : public CObject
{ ... class definition ... };

DLL のビルド時には通常、エクスポートする関数のプロトタイプやクラスを含むヘッダー ファイルを作成し、そのヘッダー ファイル内の宣言に __declspec(dllexport) を追加します。コードを読みやすくするために、次のように __declspec(dllexport) 用のマクロを定義して、そのマクロをエクスポートする各シンボルに使います。

#define DllExport   __declspec( dllexport )

__declspec(dllexport) は、関数名を DLL のエクスポート テーブルに格納します。テーブル サイズの最適化方法については、「名前ではなく序数による DLL 関数のエクスポート」を参照してください。

ただ単に__declspec(dllexport)を付けて シンボルを定義しろ、と、そういうことです。
試しに関数をエクスポートしてみます。 まずAppWizardでスケルトンを作成。あとはひたすらコーディング。

[AppWizard]-[Win32 Dynamic-Link Library]- [単純なDLLプロジェクト]あたりで作成します。 プロジェクト名は"test"でやってみます。

// test.cpp : DLL アプリケーション用のエントリ ポイントを定義します。
//

#include "stdafx.h"

BOOL APIENTRY DllMain(HANDLE hModule,
                      DWORD ul_reason_for_call,
                      LPVOID lpReserved)
{
    return TRUE;
}

作成されたのはソースファイル1個と プリコンパイル済ヘッダー関連(StdAfx.h,StdAfx.cpp)です。 実行可能ファイルのスケルトンにはWinMain関数が追加されていますが、 代わりにDllMainという関数が追加されているだけです。 この関数はWinMainとかDOSのmain関数と同じような役割を果たすもので、 DLLがロードされれば最初にこの関数が呼ばれます。 ただし、WinMainなどとは違って、ここにだらだらと書くことはあまり無く、 グローバル変数の初期化とか、ちっちゃなこと(謎)を書きます。 パラメータについては良く分からんです。(ダメジャン

ようはここに関数を追加すればいいんですよ。 簡単な例ということで、二つの数の相加平均を求める関数を定義します。
(もうちょいましな関数書けや) こんな感じでしょうか。

// test.cpp : DLL アプリケーション用のエントリ ポイントを定義します。
//

#include "stdafx.h"
#include "test.h" // さりげなくヘッダーをインクルード

BOOL APIENTRY DllMain(HANDLE hModule,
                      DWORD ul_reason_for_call,
                      LPVOID lpReserved)
{
    return TRUE;
}

// 出た!ヘボ関数
int average(int n1,int n2)
{
    return (n1+n2)/2;
}

ただ関数を書けばいいんだって。 あとはインポート時のためのヘッダーを作るだけです。 DLLを利用してもらうときは、ビルドしてできたDLLファイルと LIBファイル(インポートライブラリという)とヘッダーファイルの 三つが必要になります。
(インポートライブラリはなくても、どうにかなりますが…)

// test.h : TEST DLLのヘッダー

#ifndef __TEST_H__
#define __TEST_H__

#ifdef TEST_EXPORTS
#define _EXPORT __declspec(dllexport)
#else
#define _EXPORT __declspec(dllimport)
#endif /* TEST_EXPORTS */

_EXPORT int average(int,int);

#endif /* __TEST_H__ */

プリプロセッサばっか。なんだかなぁ。(笑

まず、複数回インクルードされる場合を防ぐ為に __TEST_H__というキーワードを定義します。これは定番ですね。
次に_EXPORTというキーワードも定義します。 TEST_EXPORTSってのはAppWizardで作成されたスケルトンでは 必ず追加されています。 これは[プロジェクト]-[設定]-[C/C++]-[プリプロセッサの定義]を見れば 載っています。プロジェクト名に応じて変わってきますので臨機応変に。 ゆえに、[_EXPORTイコール__declspec(dllexport)]となります。 キーワードを定義して、間接的にエクスポートする(?)メリットは TEST_EXPORTSの定義されていないプロジェクトで このヘッダーがインクルードされたときに明らかになります。 そのとき、_EXPORTイコール__declspec(dllimport)となり、 関数はインポートされるからです。インポートについては 「エクスポートとインポートとリンク」 を見てください。 あとは_EXPORTを付けて関数を宣言すればいいわけです。

Jun. 29, 2002