Pergunta

Eu tenho implementado um muito básico "plug-in sistema" como parte de um biblioteca estática . Cada "plug-in" implementa o suporte para um formato de imagem específico, por exemplo, GIF, JPEG, etc .. Além disso, eu tenho um Singleton (uma classe chamada PluginManager) que mantém uma lista de todos os plug-ins disponíveis.

A parte complicada é que eu quero ativar / desativar os plug-ins, adicionando ou removendo seus arquivos de origem do arquivo de projeto. Para conseguir isso, cada plug-in cria uma variável global (com nomes diferentes) e registra o plug-in no construtor dessa classe para PluginManager.

Algo como isto para o formato JPEG ...

struct JPEGPlugin
{
  // constructor will register plugin
  JPEGPlugin()
  {
    PluginManager::Singleton().RegisterPlugin(this);
  }

  // plenty of other code
  ...
};

JPEGPlugin jpeg_instance;  // instantiate in global scope

No entanto, enquanto isso funciona perfeitamente em teoria, ele falha ao ligar esta biblioteca estática para outro código para construir um executável. Enquanto este executável não acessa os globals plugins (como jpeg_instance), o vinculador não ver uma conexão (ele ignora completamente os efeitos colaterais do construtor) e não inclui o código no executável final. Em outras palavras, o plug-in JPEG não está disponível no aplicativo final.

Eu corri para os problemas de um par de vezes ao longo dos anos, e eu sempre procurei na net para soluções. Cada vez, eu só páginas que basicamente dizer que é um problema conhecido encontrado e que eu tenho que viver com ela.

Mas talvez alguém no SO sabe como fazer este trabalho?

Foi útil?

Solução

Eu não sei se isso uma solução para a maneira como você resolveu esse problema, mas tivemos um problema semelhante com registro estático de uma fábrica de objeto e no Visual Studio resolvemos-lo, declarando as classes envolvidas com __declspec (dllexport) isso era necessário, embora as bibliotecas envolvidas não eram dlls. Mas sem esta o ligador seria omitir as classes não referenciados.

A solução de registo nós trabalhamos um pouco diferente pouco e não envolveu Pilha alocada objetos. I elevado partes de CPP-unidade, que é também onde i descoberto a abordagem iirc __declspec.

[editar] Nós também tivemos que #include a declaração para a classe registrada de alguma parte do código.

Outras dicas

Uma vez que é um libary estático, você pode considerar ter o gerente registrar os plugins (em vez dos plugins registrando-se). O arquivo de cabeçalho pode definir algum símbolo preproc (ie JPEG_PLUGIN) que controla se ou não o gerente registra o plug-in baseado na inclusão do cabeçalho:

#include "JpegPlugin.h"

void PluginManager::RegisterPlugins()
{
#idef JPEG_PLUGIN
    RegisterPlugin(&jpeg_instance);
#endif
}

JpegPlugin.h não precisa necessariamente incluir a definição do JpegPlugin. Poderia ser algo como isto:

#ifndef JPEG_PLUGIN_HEADER
#define JPEG_PLUGIN_HEADER

#if 0 // change this to 1 to use the plugin
#define JPEG_PLUGIN
#include "Jpeg_PluginCls.h"
#endif

#endif

Esta é uma continuação a Harald Scheirich resposta .

Eu fiz algumas experiências, e parece que MSVC ++ Modo versão 2005 da (mas não Debug Mode) vai se transformar na bandeira /OPT:REF para o vinculador, que de acordo com o link documentação , irá causar quaisquer símbolos sem referência a ser removido do EXE final. E, a página da Web para __declspec(selectany) parece indicar que os construtores para objetos globais não são considerados como sendo referências a um objeto (incorretamente IMHO, mas, se você tiver). Então, meu palpite é que este problema "vai embora" para compilações de depuração - que é correto

?

Então, eu acho sugestão de usar __declspec(dllexport) de Harald é uma maneira conveniente de marcar o símbolo como "referenciado" porque ele é especificado dentro do código fonte. Se por algum motivo você queria evitar a exportação do símbolo, eu suspeito que você poderia fazer a mesma coisa ou usando o /INCLUDE:mysymbol vinculador bandeira , ou desligar a bandeira /OPT:REF.

Por favor:

  1. adicionar o projeto lib estática como uma referência para o projeto exe
  2. definir tanto de "dependências de biblioteca de vínculo" e "Use link da biblioteca dependência como entradas" como verdadeiro.

Veja este: config

Quando "Usar ligar dependência biblioteca como entradas" está definida como Sim, as ligações do sistema projeto no ficheiros.OBJ para .libs produzidos por projetos dependentes. Então, todos os símbolos são keeped.

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