Comportamento estranho com plugins carregados dinamicamente

1

Eu escrevi um sistema simples de Plugin para um projeto multiplataforma (windows, linux e arm linux). Estou usando o Qt 5.7 para esse propósito.

Em todos os plugins, a seguinte estrutura de dados é exportada:

struct ConnectorInfo
{
    const char *filename;
    const char *name;
    int version;
    const char *description;
    bool hasSource;
    bool hasSink;
    CreateConnectorFuncPtr createFunc;
};


#define CONNECTOR_PLUGIN(pluginName, pluginVersion, pluginDesc, hasSource, hasSink, createFunc)     \
  extern "C" {                                               \
                                                             \
      CONNECTOR_EXPORT ConnectorInfo connectorInfos =        \
      {                                                      \
          __FILE__,                                          \
          pluginName,                                        \
          pluginVersion,                                     \
          pluginDesc,                                        \
          hasSource,                                         \
          hasSink,                                           \
          createFunc                                         \
      };                                                     \
  }

In the main cpp file of the plugin:


extern "C"
{

    Connector *  CreateConnector(librt::ConnectorType type)
    {
        switch(type) {
        case ConnectorType::SOURCE:
            return new SourceConnectorTest();
        default:
            break;
        }
        qWarning() << "<libconnector_test::CreateConnector> : No connector found with type" << int(type);
        return nullptr;
    }
    CONNECTOR_PLUGIN("TEST", 1, "Test Connector (Source only)", true, false, CreateConnector)
}

Os plug-ins são carregados com QLibrary::load() e a estrutura de dados connectorInfos é carregada com QLibrary::resolve() .

Funciona bem no Windows ... mas não no Linux! Uma coisa muito estranha aconteceu. Eu consertei, mas não entendo como isso poderia ocorrer.

Basicamente, tenho dois plugins baseados no modelo acima:

  • libconnector_A.so
  • libconnector_B.so

libconnector_A.so é carregado

  • A estrutura de dados connectorInfos é carregada em @ 0x7f052540dbc0
  • Seu endereço createFunc é carregado em @ 0x7f052beb9efc
  • Outros campos na estrutura de dados estão corretos

libconnector_B.so é carregado

  • A estrutura de dados connectorInfos é carregada em @ 0x7f052c0bfd40
  • Seu endereço createFunc também é carregado em @ 0x7f052beb9efc
  • Outros campos na estrutura de dados estão corretos

Eu não entendo porque a função está carregada no mesmo endereço. Portanto, quando createFunc de B é chamado ... createFunc de A é invocado.

Eu tentei desesperadamente mudar o nome de createFunc em A:

extern "C"
{  Connector *  CreateConnectorTest (librt::ConnectorType type)... }

em vez de

extern "C"
{  Connector *  CreateConnectorTest (librt::ConnectorType type)... }

... e finalmente funcionou!

Honestamente, não sou especialista em sistemas Linux e suas políticas dinâmicas de compartilhamento compartilhado, mas realmente não entendo por que a alteração do nome da função corrige esse problema.

Qualquer explicação / sugestão / crítica é bem-vinda.

Z.

    
por Zyend 01.06.2017 / 10:40

0 respostas