Pergunta

Quais são as formas “normais” para fazer plug-ins em linguagens compiladas (C # / C / C ++ / D)? Eu estou interessado especificamente na linguagem abordagens agnósticos, mas específico de idioma não é inaceitável.

Por enquanto, “tempo de compilação” plug em abordagens (apenas incluir o código ou não e tudo funciona) são válidos, mas as coisas que podem migrar para uma abordagem mais dinâmica são os preferidos.

Em relação ao tipo de tempo de execução, eu estou mais interessado na mecânica do carregamento do plug-in e outros enfeites que projetar o plug-in / app da interface

EDIT: BTW o plugin seria um escravo não um mestre. A ação básica de um plug-in seria a de que sob uma dada situação, seria chamada a "fazer a sua coisa" e ser dado um objeto ambiente que ele deve usar para obter o que ele precisa para operar.

Foi útil?

Solução

Para linguagens compiladas (onde compilados significa que o programa é executado como um executável nativo, sem qualquer tipo de máquina virtual), você praticamente necessidade de usar algum tipo de específico da plataforma compartilhada abordagem biblioteca. No Windows, isso significa usar DLLs.

Você define sua interface plug-in em termos de um conjunto de funções (com nomes específicos, argumentos e convenções de chamada). Em seguida, você carregar os endereços das funções dentro da biblioteca compartilhada e ir para a cidade. No Windows, isso significa usar GetProcAddress () e, em seguida, converter o valor de retorno para um ponteiro de função do tipo apropriado em C, ou qualquer que seja o equivalente está no idioma que você está usando.

Outra opção que pode ou não pode ser mais desejável seria para executar uma máquina virtual para outro idioma dentro de sua aplicação nativa, e têm plugins ser código para esse idioma. Por exemplo, você poderia executar um Python VM usando CPython e dinamicamente carregar módulos Python.

Outras dicas

Mono.Addins parece ser uma boa solução para .NET. Eu acredito que inclui API para permitir que você baixar plugins (ou suplementos) de um repo e dinamicamente carregá-lo em um running montagem.

Descobri que as partes duras sobre plugins são: encontrá-los, resolvendo suas dependências, e lidar com questões de versão. Como você lida com estas questões devem ser claro para você e para o seu plug-in autores. Se você receber essas questões errado, ele irá causar nenhum fim da dor. Eu olhava para linguagens de script e aplicações que utilizam plugins de ideias sobre o que funciona bem.

Construtores estáticos são mais frequentemente do que não, "inteligente" no mau sentido. Desde que você está indo ter que carga (C / C ++: dlopen e amigos no Linux) os plugins um de cada vez de qualquer maneira (no caso dinâmico), assim como você pode manifestamente inicializado-los como você fazê-lo. Entre outras coisas, que podem lhe dar uma oportunidade para rejeitar plugins sem esperado API.

Nota, você não tem que usar bibliotecas de carga dinâmica para plugins. Outros mecanismos também podem ser usados: memória compartilhada, soquetes, etc ....

É realmente depende do que você quer fazer. O padrão comum Unix como visto na Emacs eo Gimp é escrever um programa que consiste de um pequeno componente compilado que expõe a funcionalidade essencial que uma interpretado usos de componentes para fazer tudo. Pluglins que fornecem nova funcionalidade que pode ser construído em cima do aplicativo são fáceis, mas você precisa ser muito flexível nas primatives fornecidos para que isso seja possível. No extremo oposto imaginar um editor de fotos que pode salvar em vários formatos. Você deseja permitir que as pessoas a escrever os seus próprios manipuladores de formato de arquivo. Isso requer tornando seu uso código de um simples conjunto de primitivas, em seguida, escolher uma implementação em tempo de execução. Em linha reta (Unix) uso C dlopen, em C ++ usar extern C, que limita o que você pode fazer e dlopen. Em Objective-C você tem uma classe para fazer isso por você. No primeiro caso, você está fazendo ou reutilizar um intérprete para que você tenha total liberdade para fazê-lo como quiser.

Para um plugin do tipo escravo, onde cada plugin encapsula uma implementação diferente de um conjunto comum de funções, gostaria apenas de depositar as DLLs em uma pasta de plugin conhecido para o aplicativo host (por exemplo, "c: \ Program Files \ myapp \ plugins ), e em seguida, chamar as DLLs do anfitrião através de Reflexão.

Você poderia fazer algum tipo de processo de registo elaborado quando cada DLL é instalado, mas eu nunca tinha experimentado quaisquer problemas com os plugins-em-um-pasta simples abordagem.

Edit: Para fazer isso em C #, basta adicionar uma classe pública para a DLL (chamado "Plug-in" ou qualquer outro), e implementar funções necessárias lá. A partir do seu host, você, em seguida, criar um objeto do tipo plug-in e chamar seus métodos (todos usando Reflexão).

Interfaces com um registo void (EventSource) parecem funcionar bem - veja IHttpModule.Init (HttpApplication ) para um exemplo.

Isso permite que o autor aplicativo (que controla EventSource) para adicionar eventos quando necessário, sem a necessidade de estender a interface IPlugin (inevitavelmente levando a IPluginEx, IPlugin2, IPlugin2Ex, etc.)

Uma abordagem que eu usei (em .NET) é ter o anfitrião fazer uma chamada inicial para o plug-in (via Reflexão), a partir do plug-in e passar uma referência para o host que o plugin salva. O plug-in, em seguida, chama métodos no host (também através de reflexão), se necessário.

Eu acho que com a maioria dos plugins, as chamadas normalmente seria feito em outra direção (ou seja, o anfitrião chamaria o plugin, se necessário). No meu caso, os plugins próprios tinham elementos de interface do usuário que precisava fazer uso da funcionalidade de host.

questões de implementação do módulo de baixo nível de lado (por exemplo DLLs do Windows e questões de implementação), um motor de jogo que eu uso só tem uma função de registro global nas DLLs, e tentativas de encontrar e chamar-lo em cada dll no diretório plugin. a função registartion faz qualquer contabilidade necessária para expor a funcionalidade.

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