標準 MFC DLL でのデータベース、OLE、およびソケット MFC 拡張 DLL の使用

標準 MFC DLL から MFC 拡張 DLL を使用する場合、MFC 拡張 DLL が標準 MFC DLL の CDynLinkLibrary オブジェクト チェーンに接続されていないと、1 つまたは複数の関連する問題が発生する可能性があります。 MFC データベース、OLE、およびソケット対応 DLL のデバッグ バージョンは MFC 拡張 DLL として実装されているため、これらの MFC 機能を使用していると、独自の MFC 拡張 DLL を明示的に使用していなくても、同様の問題が発生する可能性があります。 次のような現象が発生します。

  • MFC 拡張 DLL で定義されているクラスの型のオブジェクトを逆シリアル化しようとすると、"警告: アーカイブから CYourClass を読み込めません。 クラスが定義されていません。" というメッセージがトレース デバッグ ウィンドウに表示され、このオブジェクトのシリアル化に失敗します。

  • 不正なクラスを示す例外がスローされる場合があります。

  • MFC 拡張 DLL に格納されているリソースは、戻り値NULLまたは不適切なリソース ハンドルが原因AfxFindResourceHandleで読み込みに失敗します。

  • DllGetClassObjectDllCanUnloadNow、および COleObjectFactoryUpdateRegistryRevokeRevokeAll、および RegisterAll メンバー関数で、MFC 拡張 DLL 内に定義されているクラス ファクトリを見つけることができません。

  • AfxDoForAllClasses が MFC 拡張 DLL 内のクラスに対して機能しません。

  • 標準の MFC データベース、ソケット、または OLE リソースの読み込みに失敗します。 たとえば、標準 MFC DLL で MFC データベース クラスが正しく使用されている場合でも、AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) から空の文字列が返されます。

これらの問題の解決策は、オブジェクトを作成する MFC 拡張 DLL に初期化関数を作成 CDynLinkLibrary してエクスポートすることです。 MFC 拡張 DLL を使用する標準 MFC DLL から、この初期化関数を 1 回だけ呼び出します。

MFC OLE、MFC データベース (または DAO)、または MFC ソケットのサポート

標準 MFC DLL 内で MFC OLE、MFC データベース (または DAO)、または MFC ソケットのサポートを使用している場合は、それぞれ MFC デバッグ MFC 拡張 DLL MFCOxxD.dllMFCDxxD.dllMFCNxxD.dll (xx はバージョン番号) が自動的にリンクされます。 使用する DLL ごとに、定義済みの初期化関数を呼び出してください。

  • データベース サポートの場合は、標準 MFC DLL の CWinApp::InitInstance 関数に AfxDbInitModule の呼び出しを追加します。 この呼び出しは、基本クラスの呼び出し、または MFCDxxD.dll にアクセスする追加コードの前に行うようにしてください。 この関数はパラメーターを取らず、void が返されます。

  • OLE サポートの場合は、標準 MFC DLL の CWinApp::InitInstance 関数に AfxOleInitModule の呼び出しを追加します。 COleControlModule::InitInstance 関数では AfxOleInitModule が既に呼び出されているため、OLE コントロールを作成して COleControlModule を使用する場合は、この呼び出しを AfxOleInitModule に追加しないでください。

  • ソケット サポートの場合は、標準 MFC DLL の CWinApp::InitInstanceAfxNetInitModule の呼び出しを追加します。

MFC DLL とアプリケーションのリリース ビルドでは、データベース、ソケット、または OLE のサポートに個別の DLL が使用されません。 ただし、リリース モードでは、これらの初期化関数を安全に呼び出すことができます。

CDynLinkLibrary オブジェクト

この記事の始めに説明した各操作中、MFC では特定の値またはオブジェクトを検索する必要があります。 たとえば、逆シリアル化中は、MFC では、現在使用可能なすべてのランタイム クラスを検索して、アーカイブ内のオブジェクトを適切なランタイム クラスに一致させる必要があります。

これらの検索の一環として、MFC は、オブジェクトのチェーン CDynLinkLibrary を歩くことで、使用中のすべての MFC 拡張 DLL をスキャンします。 CDynLinkLibrary オブジェクトは、構築中にチェーンに自動的にアタッチされ、初期化中に各 MFC 拡張 DLL によって自動的に作成されます。 すべてのモジュール (アプリケーションまたは標準 MFC DLL) には、CDynLinkLibrary オブジェクトの独自のチェーンがあります。

MFC 拡張 DLL をチェーンに CDynLinkLibrary 接続するには、MFC 拡張 DLL を使用するすべてのモジュールのコンテキストでオブジェクトを作成 CDynLinkLibrary する必要があります。 標準 MFC DLL で MFC 拡張 DLL を使用するには、拡張 DLL によって、CDynLinkLibrary オブジェクトを作成するエクスポートされた初期化関数が提供される必要があります。 MFC 拡張 DLL を使用するすべての標準 MFC DLL は、エクスポートされた初期化関数を呼び出す必要があります。

MFC 拡張 DLL を MFC アプリケーションからのみ使用し、標準 MFC DLL からは使用しない場合は、MFC 拡張 DLL の DllMain 関数に CDynLinkLibrary オブジェクトを作成するだけで十分です。 これは、MFC DLL ウィザードの MFC 拡張 DLL コードによって実行されることです。 MFC 拡張 DLL を暗黙的に読み込む場合は、アプリケーションが起動する前に DllMain が読み込まれ、実行されます。 すべての CDynLinkLibrary 作成は、MFC DLL が MFC アプリケーション用に予約する既定のチェーンにワイヤードされます。

1 つのチェーン内の 1 つの MFC 拡張 DLL から複数の CDynLinkLibrary オブジェクトを持つことはお勧めしません。 MFC 拡張 DLL がメモリから動的にアンロードされる可能性がある場合は特にそうです。 初期化関数を 1 つのモジュールから複数回呼び出さないでください。

サンプル コード

このサンプル コードでは、標準 MFC DLL が MFC 拡張 DLL に暗黙的にリンクしていることを前提としています。 暗黙的にリンクするには、標準 MFC DLL をビルドするときに、MFC 拡張 DLL のインポート ライブラリ (LIB ファイル) にリンクします。

以下の行を MFC 拡張 DLL のソースに含める必要があります。

// YourExtDLL.cpp:

// standard MFC extension DLL routines
#include "afxdllx.h"

static AFX_EXTENSION_MODULE extensionDLL;

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        // MFC extension DLL one-time initialization
        if (!AfxInitExtensionModule(extensionDLL, hInstance))
           return 0;
    }
    return 1;   // ok
}

// Exported DLL initialization is run in context of
// application or regular MFC DLL
extern "C" void WINAPI InitYourExtDLL()
{
    // create a new CDynLinkLibrary for this app
    new CDynLinkLibrary(extensionDLL);

    // add other initialization here
}

必ず InitYourExtDLL 関数をエクスポートしてください。 次に示すように、__declspec(dllexport) を使用するか、DLL の DEF ファイルにエクスポートすることができます。

// YourExtDLL.Def:
LIBRARY      YOUREXTDLL
CODE         PRELOAD MOVEABLE DISCARDABLE
DATA         PRELOAD SINGLE
EXPORTS
    InitYourExtDLL

MFC 拡張 DLL を使用して、標準 MFC DLL 内に CWinApp 派生オブジェクトの InitInstance メンバーへの呼び出しを追加します。

// YourRegularDLL.cpp:

class CYourRegularDLL : public CWinApp
{
public:
    virtual BOOL InitInstance(); // Initialization
    virtual int ExitInstance();  // Termination

    // nothing special for the constructor
    CYourRegularDLL(LPCTSTR pszAppName) : CWinApp(pszAppName) { }
};

BOOL CYourRegularDLL::InitInstance()
{
    // any DLL initialization goes here
    TRACE0("YOUR regular MFC DLL initializing\n");

    // wire any MFC extension DLLs into CDynLinkLibrary chain
    InitYourExtDLL();

    return TRUE;
}

目的に合ったトピックをクリックしてください

さらに詳しくは次のトピックをクリックしてください

関連項目

MFC 拡張 DLL