2009-12-10 8 views
8

Tengo una DLL que necesita acceder a los datos almacenados en contenedores STL en la aplicación de host. Debido a que C++ no tiene ABI estándar, y quiero admitir diferentes compiladores, la interfaz entre la aplicación y la DLL básicamente tiene que seguir siendo plain-old-data.Cómo exponer la lista STL sobre el límite de DLL?

Para los vectores, esto es relativamente sencillo. Puede devuelva el bloque de memoria del vector, ya que se garantiza que sea contigious:

// To return vector<int> data 
virtual void GetVectorData(const int*& ptr, size_t& count) const 
{ 
    if (!vec.empty()) 
     ptr = &(vec.front()); 

    count = vec.size(); 
} 

Ahora la DLL puede tener acceso de lectura seguro a los datos del vector a través de esa interfaz. La DLL también puede ajustar esto para copiar el contenido en un vector para sí mismo también.

¿Qué pasa con las listas de STL (y deques) though? ¿Hay alguna otra manera directa de permitir el acceso a través de un límite de DLL? ¿O tendré que recurrir a algún tipo de interfaz GetFirst()/GetNext()? Puede que tenga que hacer esto para muchas listas, por lo que sería bueno tener una solución tan simple como la de los vectores.

Respuesta

7

Tal vez pueda pasar algo así como "maneja" para listar/iterar iteradores? Estos tipos de identificador serían opacos y se declararían en un archivo de encabezado que enviaría a los usuarios. Internamente, necesitaría mapear los valores del manejador para mostrar/iterar iteradores. Básicamente, el usuario podría escribir código como:

ListHandle lhi = GetListDataBegin(); 
const ListHandle lhe = GetListDataEnd(); 

while (lhi != lhe) 
{ 
    int value = GetListItem(lhi); 
    ... 
    lhi = GetNextListItem(lhi); 
} 
1

la interfaz entre la aplicación y DLL, básicamente, tiene que seguir siendo llanura de edad-datos.

No necesariamente. Debe asegurarse de usar la misma versión del compilador. Además, las configuraciones de compilación que afectan el diseño de los objetos STL son exactamente las mismas entre la DLL y la aplicación.

Si liberas el dll en la naturaleza, tienes razón en preocuparte por exponer STL a través de los límites de dll. Sin embargo, si todo está bajo su control y es puramente interno (o si puede hacer cumplir estrictamente las configuraciones/compiladores de terceros), estará bien.

+0

Tiene razón de que podría salirse con la suya si todos los ajustes de compilación son los mismos. Pero esto es para una arquitectura de complementos y me gustaría admitir diferentes compiladores. He editado la pregunta para aclarar esto. – AshleysBrain

+0

Estoy de acuerdo con esto, pero tal vez deberías enfatizar que no es solo el diseño: el código debe haberse compilado con la misma versión del compilador, de modo que las implementaciones de métodos como nuevo y eliminar coincidan. –

+0

Si aplica estrictamente las configuraciones de compilación/versiones de compilador y todo está bajo su control, ¿cuál es la ventaja de las DLL frente a usar bibliotecas estáticas y vincular todo en un solo ejecutable? –

10

Puede pasar objetos entre stl DLL y apoyar diferentes compiladores si se tiene cuidado en que se ejemplariza cada tipo STL. Necesita algunas macros inteligentes "DLLEXPORT": utilizo el siguiente conjunto para admitir con éxito VC y gcc.

#ifdef WIN32 
#ifdef MYDLLLIB_EXPORTS  // DLL export macros 
#define MYDLLLIB_API __declspec(dllexport) 
#define MYDLLLIB_TEMPLATE 
#else 
#define MYDLLLIB_API __declspec(dllimport) 
#define MYDLLLIB_TEMPLATE extern 
#endif 
#else      // Not windows --- probably *nix/bsd 
#define MYDLLLIB_API 
#ifdef MYDLLLIB_EXPORTS 
#define MYDLLLIB_TEMPLATE 
#else 
#define MYDLLLIB_TEMPLATE extern 
#endif 
#endif // WIN32 

Al compilar su DLL, defina MYDLLLIB_EXPORTS. En la DLL a continuación, puede crear una instancia de cada tipo STL que desea utilizar, por ejemplo, listas o vectores de cadenas

MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::vector<std::string>; 
MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::list<std::string>; 

consumidores de su DLL (que no tienen definidos MYDLLLIB_EXPORTS) A continuación, verá

extern template class __declspec(dllimport) std::vector<std::string>; 

y utiliza el código binario exportado desde tu DLL en lugar de crear el suyo propio.

+0

Esa es una solución muy interesante. ¿Tendría que hacer lo mismo para std :: vector :: iterator y std :: list :: iterator? ¿Es de la misma manera para el DLL que consume clases STL desde un host EXE? – AshleysBrain

+0

No necesita crear instancias de los iteradores porque al crear una instancia de una clase de contenedor stl específica también obtiene el código para todas las clases dentro de la clase contenedora. No sé sobre el consumo de clases STL desde un host EXE. No lo he intentado personalmente, así que si deseas seguir este método, tendrás que experimentar un poco con una prueba simple. – mcdave

+2

Aquí está en MSDN: http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q168958 – k06a

Cuestiones relacionadas