Compartir a través de


Uso de archivos DLL de extensión MFC de base de datos, OLE y Sockets en archivos DLL de MFC normales

Cuando se usa un archivo DLL de extensión MFC desde un archivo DLL de MFC normal, si el primero no está conectado a la cadena de objetos CDynLinkLibrary del segundo, podría encontrarse con uno o varios problemas relacionados. Dado que las versiones de depuración de la base de datos MFC, OLE y Sockets que admiten archivos DLL se implementan como archivos DLL de extensión MFC, es posible que observe problemas similares si usa estas características de MFC, incluso si no utiliza explícitamente ninguno de sus propios archivos DLL de extensión MFC. Algunos de los síntomas son los siguientes:

  • Al intentar deserializar un objeto de un tipo de clase definida en el archivo DLL de extensión MFC, el mensaje "Advertencia: No se puede cargar CYourClass desde el archivo. Clase sin definir." en la ventana de depuración TRACE y el objeto no se podrá serializar.

  • Se puede producir una excepción que indica una clase incorrecta.

  • Los recursos almacenados en el archivo DLL de extensión MFC no se cargan porque AfxFindResourceHandle devuelve NULL o un identificador de recursos incorrecto.

  • DllGetClassObject, DllCanUnloadNow y las funciones miembro UpdateRegistry, Revoke, RevokeAll y RegisterAll de COleObjectFactory no pueden encontrar un generador de clases definido en el archivo DLL de extensión MFC.

  • AfxDoForAllClasses no funciona con ninguna clase del archivo DLL de extensión MFC.

  • La base de datos MFC estándar, los sockets o los recursos OLE no se pueden cargar. Por ejemplo, AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) devuelve una cadena vacía, incluso cuando el archivo DLL de extensión MFC usa correctamente las clases de la base de datos MFC.

La solución a estos problemas es crear y exportar una función de inicialización en el archivo DLL de extensión MFC que crea un CDynLinkLibrary objeto . Llame a esta función de inicialización exactamente una vez desde cada archivo DLL de MFC estándar que use el archivo DLL de extensión MFC.

Compatibilidad con OLE de MFC, base de datos MFC (o DAO) o sockets MFC

Si utiliza alguna compatibilidad con OLE de MFC, base de datos MFC (o DAO) o Sockets de MFC, respectivamente, en el archivo DLL de MFC normal, los archivos DLL de extensión MFC de depuración de MFC MFCOxxD.dll, MFCDxxD.dll y MFCNxxD.dll (donde xx es el número de versión) se vinculan automáticamente. Con cada uno de estos archivos DLL que se usen, llame a una función de inicialización predefinida:

  • Para la compatibilidad con la base de datos, agregue una llamada a AfxDbInitModule a la función CWinApp::InitInstance de los archivos DLL de MFC normales. Asegúrese de que esta llamada se produce antes de que cualquier llamada de clase base o cualquier código agregado accedan a MFCDxxD.dll. Esta función no toma ningún parámetro y devuelve void.

  • Para la compatibilidad con OLE, agregue una llamada a AfxOleInitModule a la función CWinApp::InitInstance de los archivos DLL de MFC normales. La función COleControlModule::InitInstance ya llama a AfxOleInitModule, por lo que si está creando un control OLE y usa COleControlModule, no debe agregar esta llamada a AfxOleInitModule.

  • Para la compatibilidad con Sockets, agregue una llamada a AfxNetInitModule a la función CWinApp::InitInstance de los archivos DLL de MFC normales.

Las compilaciones de versión de las aplicaciones y archivos DLL de MFC no usan archivos DLL independientes para la compatibilidad con la base de datos, OLE o Sockets. Sin embargo, es seguro llamar a estas funciones de inicialización en modo de versión.

Objetos CDynLinkLibrary

Durante cada operación mencionada al principio de este artículo, MFC necesita buscar un valor u objeto determinados. Por ejemplo, durante la deserialización, MFC necesita buscar en todas las clases en tiempo de ejecución actualmente disponibles para que los objetos del archivo coincidan con su clase en tiempo de ejecución adecuada.

Como parte de estas búsquedas, MFC examina todos los archivos DLL de extensión de MFC en uso caminando por una cadena de CDynLinkLibrary objetos. CDynLinkLibrary Los objetos se adjuntan automáticamente a una cadena durante su construcción y se crean mediante cada DLL de extensión MFC a su vez durante la inicialización. Cada módulo (aplicación o archivo DLL de MFC normal) tiene su propia cadena de objetos CDynLinkLibrary.

Para que un archivo DLL de extensión MFC se encadene en una CDynLinkLibrary cadena, debe crear un CDynLinkLibrary objeto en el contexto de cada módulo que use el archivo DLL de extensión MFC. Para utilizar un archivo DLL de extensión de MFC en archivos DLL de MFC normales, el archivo DLL de extensión debe proporcionar una función de inicialización exportada que cree un objeto CDynLinkLibrary. Cada archivo DLL de MFC estándar que use el archivo DLL de extensión MFC debe llamar a la función de inicialización exportada.

Si solo va a utilizar un archivo DLL de extensión de MFC de una aplicación MFC y nunca de un archivo DLL de MFC normal, basta con crear el objeto CDynLinkLibrary en la función DllMain del archivo DLL de extensión de MFC. Esto es lo que hace el código DLL de extensión de MFC del Asistente para archivos DLL de MFC. Al cargar un archivo DLL de extensión MFC de manera implícita, DllMain se carga y ejecuta antes de que se inicie la aplicación. Las CDynLinkLibrary creaciones se conectan a una cadena predeterminada que el archivo DLL de MFC reserva para una aplicación MFC.

No es aconsejable tener varios objetos CDynLinkLibrary de un archivo DLL de extensión MFC en una cadena. Esto especialmente cierto si el archivo DLL de extensión de MFC se puede descargar dinámicamente de la memoria. No llame a la función de inicialización más de una vez desde cada módulo.

Código de ejemplo

En este código de ejemplo se supone que el archivo DLL de MFC normal crea un vínculo implícitamente con el archivo DLL de extensión de MFC. Para crear un vínculo implícitamente, cree un vínculo a la biblioteca de importación (archivo LIB) del archivo DLL de extensión de MFC cuando compile el archivo DLL de MFC normal.

Las líneas siguientes deben estar en el código fuente del archivo DLL de extensión MFC:

// 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
}

Asegúrese de exportar la función InitYourExtDLL. Puede usar __declspec(dllexport) o exportarlo en el archivo DEF de su archivo DLL, como se muestra aquí:

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

Agregue una llamada al miembro InitInstance del objeto derivado de CWinApp en cada archivo DLL de MFC estándar mediante el archivo DLL de extensión MFC:

// 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;
}

¿Qué desea hacer?

¿Qué más desea saber?

Consulte también

Archivos DLL de extensión MFC