Eu gosto da tecnologia COM. Mas não falaremos sobre tecnologia, elogios ou deficiências do COM, mas a experiência de portar e implementar no Linux. Uma bicicleta? Conveniência?
Não vamos nos concentrar nisso.
Objeto COM (1)Em termos gerais, um objeto de uma classe que implementa pelo menos uma interface COM. A implementação do objeto está oculta principalmente em uma biblioteca conectada dinamicamente chamada servidor COM (2) , as interfaces são publicadas e distribuídas para uso.
Interface COM, uma classe abstrata que contém apenas funções virtuais puras. Uma interface IUnknown especial é destacada, qualquer objeto COM deve implementar essa interface.
Cada interface COM deve conter seu próprio identificador. No COM, é determinado pela estrutura do GUID e aqui enfrentaremos a primeira desvantagem do COM. O GUID é incompreensível e não lê bem, e tudo o mais descrito no Wiki. Precisamos do mesmo, mas de uma maneira mais legível e compreensível (vamos chamá-lo de uiid).
IDesconhecido e uiid#define define_uiid(name) \ inline static const std::string& guid() { const static std::string idn(dom_guid_pre_name #name); return idn; } namespace Dom { using uiid = std::string; using clsuid= std::string; struct IUnknown { virtual long AddRef() = 0; virtual long Release() = 0; virtual bool QueryInterface(const uiid&, void **ppv) = 0; define_uiid(Unknown) }; }
Além do identificador de interface, o identificador de classe (clsuid), necessário para criar o objeto, também é alocado. No nosso caso, porque esse é um identificador menos legível que pode determinar a essência; você pode esquecer a publicação deles por enquanto (talvez isso não seja bom).
Sumário
Um objeto COM que contém um único identificador de classe. Ele implementa pelo menos uma interface COM - IUnknown (qualquer interface COM possui um identificador de interface exclusivo). Implementações diferentes de um objeto COM podem ter o mesmo identificador de classe (exemplo: versão de lançamento e depuração).
Servidor COM (2)Uma biblioteca vinculada dinamicamente (para Linux, é um objeto compartilhado) que implementa pelo menos um objeto COM. O servidor deve exportar um conjunto específico de funções:
extern "C" bool DllCreateInstance(const uiid& iid, void** ppv)
Cria um objeto de classe por clsuid, aumenta o número de referências a isso, toda vez que o objeto é criado com êxito. A chamada para IUnknown :: AddRef também deve aumentar a contagem de referência, e IUnknown :: Release deve diminuir.
extern "C" bool DllCanUnloadNow()
Se o número de referências ao SO for 0, você poderá descarregar a biblioteca.
extern "C" bool DllRegisterServer(IUnknown* unknown)
Registra todos os servidores clsuid no "registro". Chamado uma vez durante a instalação do servidor COM.
extern "C" bool DllUnRegisterServer(IUnknown* unknown)
Exclui das entradas "registro" sobre o servidor clsuid registrado. Chamado uma vez ao desinstalar o servidor COM.
Exemplo SimpleHello, declare a interface IHello: struct IHello : public virtual Dom::IUnknown { virtual void Print() = 0; define_uiid(Hello) };
Implementação da interface: class SimpleHello : public Dom::Implement<SimpleHello, IHello> { public: SimpleHello() { printf("%s\n", __PRETTY_FUNCTION__); } ~SimpleHello() { printf("%s\n", __PRETTY_FUNCTION__); } virtual void Print() { printf("Hello from %s\n",__PRETTY_FUNCTION__); } define_clsuid(SimpleHello) }; namespace Dom { DOM_SERVER_EXPORT_BEGIN EXPORT_CLASS(SimpleHello) DOM_SERVER_EXPORT_END DOM_SERVER_INSTALL(IUnknown* unknown) { Interface<IRegistryServer> registry; if (unknown->QueryInterface(IRegistryServer::guid(), registry)) {
Um conjunto de macros oculta implementações de funções, fornecendo uma declaração e lógica mais estruturadas.
Dom :: Implement <SimpleHello, IHello> - oculta a implementação dos métodos de interface IUnknown, adiciona "sugar" ao declarar interfaces implementadas por um objeto (C ++ 11 e modelos variados):
template <typename T, typename ... IFACES> struct Implement : virtual public IUnknown, virtual public IFACES… { ... };
Interface IRegistryServer - define um conjunto de métodos para trabalhar com o "registro" de servidores COM.
"Registro" de servidores COM (3)A importância do registro pode ser subestimada, mas é provavelmente o principal pilar do COM. A Microsoft escreve no registro, cria uma estrutura complexa para descrever as interfaces e seus atributos (idl), eu fui um pouco diferente.
Na implementação, o registro é baseado no sistema de arquivos.
Que tipo de pãezinhos? Compreensibilidade, simplicidade, possibilidade de recuperação, um problema especial ao registrar um servidor, você pode definir algum tipo de espaço para nome (um diretório relativo ao registro base no qual os objetos do servidor serão registrados), assim você pode implementar a integridade e a versão dos aplicativos usando a tecnologia.
Das deficiências, possíveis problemas de segurança, a substituição de implementações de objetos.
Como usar, aplicativo de exemplo (4)Para que tudo funcione, você precisará de uma pequena "biblioteca" e um pequeno "programa".
"Biblioteca" nada mais é do que um invólucro que implementa e coleta tudo em um único todo, trabalhando com o registro, carregando / descarregando SO, criando objetos.
É o único que deve ser especificado ao criar o aplicativo. Tudo o resto, "eu quero acreditar", ela fará a si mesma.
“ Programka ” - o regsrv é, na verdade, um análogo do programa Microsoft RegSrv32 que executa as mesmas ações (+ a capacidade de especificar um espaço para nome, + a capacidade de obter uma lista de clsuid e servidores COM registrados).
amostra #include "../include/dom.h" #include "../../skel/ihello.h" int main() { Dom::Interface<Dom::IUnknown> unkwn; Dom::Interface<IHello> hello; if (Dom::CreateInstance(Dom::clsid("SimpleHello"), unkwn)) { unkwn->QueryInterface(IHello::guid(), hello); hello->Print(); } else { printf("[WARNING] Class `SimpleHello` not register.\nFirst execute command\n\tregsrv <fullpath>/libskel.so\n... and try again."); } return 0; }
Dom (5)Dom (Dynamic Object Model), minha implementação para Linux.
clone git
Obrigada