Pergunta

Eu tenho uma DLL que precisa acessar dados armazenados em contêineres STL no aplicativo host. Como o C ++ não possui ABI padrão e eu quero suportar diferentes compiladores, a interface entre o aplicativo e a DLL basicamente precisa permanecer dados antigos.

Para vetores, isso é relativamente direto. Você pode simplesmente devolver o bloco de memória do vetor, porque é garantido que seja contigioso:

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

    count = vec.size();
}

Agora, a DLL pode ter acesso seguro para leitura aos dados do vetor por meio dessa interface. A DLL também pode envolver isso para copiar o conteúdo para um vetor para si também.

E as listas STL (e deques)? Existe outra maneira direta de permitir o acesso por meio de um limite de DLL? Ou terei que recorrer a algum tipo de interface getfirst ()/getNext ()? Talvez eu precise fazer isso para muitas listas, por isso seria bom ter uma solução tão simples quanto o de vetor.

Foi útil?

Solução

Talvez você possa passar algo como "lidar" para listar/deque iteradores? Esses tipos de manipulação seriam opacos e declarados em um arquivo de cabeçalho que você enviaria para os usuários. Internamente, você precisaria mapear os valores de manipulação para listar/deque iteradores. Basicamente, o usuário escreveria código como:

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

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

Outras dicas

Você pode passar os objetos STL entre as DLLs e suportar diferentes compiladores se tiver cuidado onde instanciar cada tipo STL. Você precisa de algumas macros inteligentes "DLLEXPORT" - eu uso o seguinte conjunto para apoiar com êxito o VC e o 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

Ao compilar sua DLL, defina mydlllib_exports. Na DLL, você pode instanciar cada tipo STL que deseja usar, por exemplo, listas ou vetores de strings

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

Consumidores da sua DLL (que não têm mydlllib_exports definidos) então verá

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

e use o código binário exportado da sua DLL em vez de instanciar o seu próprio.

A interface entre o aplicativo e a DLL basicamente precisa permanecer dados antigos.

Não necessariamente. Você deve ter certeza de que a mesma versão do compilador é usada. Além disso, as configurações de construção que afetam o layout dos objetos STL são exatamente os mesmos entre a DLL e o aplicativo.

Se você lançar a DLL para a natureza, está certo em se preocupar em expor os limites da DLL. Se, no entanto, tudo estiver sob seu controle e puramente interno (ou se você puder aplicar rigidamente as configurações/compilador de construção de terceiros), você deve ficar bem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top