O que devo fazer se duas bibliotecas fornecerem uma function com o mesmo nome gerando um conflito?

O que devo fazer se eu tiver duas bibliotecas que fornecem funções com nomes equivalentes?

  • Se você controlar um ou ambos: edite um para alterar o nome e recompile Ou ver equivalentemente Ben e as respostas do desconhecido que funcionarão sem access ao código-fonte.
  • Se você não controla nenhum deles, você pode include um deles. Isso é compilar outra biblioteca ( estaticamente ligada !) Que não faz nada exceto reexportar todos os símbolos do original, exceto o ofensivo, que é alcançado através de um wrapper com um nome alternativo. Que aborrecimento
  • Adicionado depois: Como qeek diz que está falando sobre bibliotecas dinâmicas, as soluções sugeridas por Ferruccio e mouviciel são provavelmente as melhores. (Eu pareço viver há muito tempo atrás, quando a binding estática era o padrão. Isso colore meu pensamento.)

A propósito dos comentários: Por “exportação”, quero dizer, tornar visível aos módulos vinculados à biblioteca — equivalente à palavra-chave extern no escopo do arquivo. Como isso é controlado é dependente do sistema operacional e vinculador. E é algo que eu sempre tenho que procurar.

É possível renomear símbolos em um arquivo object usando objcopy --redefine-sym old=new file (veja man objcopy).

Em seguida, basta chamar as funções usando seus novos nomes e vincular com o novo arquivo de object.

No Windows, você pode usar LoadLibrary () para carregar uma dessas bibliotecas na memory e, em seguida, usar GetProcAddress () para obter o endereço de cada function que você precisa chamar e chamar as funções através de um ponteiro de function.

por exemplo

 HMODULE lib = LoadLibrary("foo.dll"); void *p = GetProcAddress(lib, "bar"); // cast p to the approriate function pointer type (fp) and call it (*fp)(arg1, arg2...); FreeLibrary(lib); 

iria obter o endereço de uma function chamada bar no foo.dll e chamá-lo.

Eu sei que os sistemas Unix suportam funcionalidades semelhantes, mas não consigo pensar em seus nomes.

Aqui está um pensamento. Abra uma das bibliotecas problemáticas em um editor hexadecimal e altere todas as ocorrências das cadeias incorretas para outra coisa. Você deve então poder usar os novos nomes em todas as chamadas futuras.

ATUALIZAÇÃO: Eu acabei de fazer isso e parece funcionar. Claro, eu não testei isso completamente – pode não ser mais do que uma ótima maneira de explodir sua perna com uma espingarda hexedit.

Você não deve usá-los juntos. Se bem me lembro, o linker emite um erro nesse caso.

Eu não tentei, mas uma solução pode ser com dlopen() , dlsym() e dlclose() que permitem manipular bibliotecas dinâmicas de maneira programática. Se você não precisar das duas funções ao mesmo tempo, poderá abrir a primeira biblioteca, usar a primeira function e fechar a primeira biblioteca antes de usar a segunda biblioteca / function.

Jurar? Tanto quanto eu sei, não há muito o que fazer se você tiver duas bibliotecas que exponham pontos de link com o mesmo nome e você precisa se conectar a ambos.

Esse problema é o motivo pelo qual o c ++ possui namespaces. Não há realmente uma ótima solução em c para 2 bibliotecas de terceiros com o mesmo nome.

Se for um object dynamic, você poderá carregar explicitamente os objects compartilhados (LoadLibrary / dlopen / etc) e chamá-lo dessa maneira. Como alternativa, se você não precisar das duas libs ao mesmo tempo no mesmo código, talvez você possa fazer algo com vinculação estática (se tiver os arquivos .lib / .a).

Nenhuma dessas soluções se aplica a todos os projetos, é claro.

Supondo que você use linux você primeiro precisa adicionar

 #include  

Declare a variável do ponteiro de function no contexto adequado, por exemplo,

 int (*alternative_server_init)(int, char **, char **); 

Como o Ferruccio afirmou em https://stackoverflow.com/a/678453/1635364 , carregue explicitamente a biblioteca que você quer usar executando (escolha suas flags favoritas)

 void* dlhandle; void* sym; dlhandle = dlopen("/home/jdoe/src/libwhatnot.so.10", RTLD_NOW|RTLD_LOCAL); 

Leia o endereço da function que você deseja chamar mais tarde

 sym = dlsym(dlhandle, "conflicting_server_init"); 

atribuir e converter da seguinte forma

 alternative_server_init = (int (*)(int, char**, char**))sym; 

Ligue de forma semelhante ao original. Finalmente, descarregar executando

 dlclose(dlhandle); 

Você deve escrever uma biblioteca wrapper em torno de um deles. A biblioteca do wrapper deve expor símbolos com nomes exclusivos e não expor os símbolos dos nomes não exclusivos.

Sua outra opção é renomear o nome da function no arquivo de header e renomear o símbolo no archive do object de biblioteca.

De qualquer forma, para usar os dois, vai ser um trabalho de hack.

Eu nunca usei dlsym, dlopen, dlerror, dlclose, dlvsym, etc., mas estou olhando para a man page, e dá um exemplo de como abrir o libm.so e extrair a function cos. O dlopen passa pelo processo de procurar por colisões? Caso contrário, o OP poderia apenas carregar as duas bibliotecas manualmente e atribuir novos nomes a todas as funções que suas bibliotecas fornecem.

Se você tiver arquivos .o lá, uma boa resposta aqui: https://stackoverflow.com/a/6940389/4705766

Resumo:

  1. objcopy --prefix-symbols=pre_string test.o para renomear os símbolos no arquivo .o

ou

  1. objcopy --redefine-sym old_str=new_str test.o para renomear o símbolo específico no arquivo .o.

A questão está se aproximando de uma década, mas há novas pesquisas o tempo todo …

Como já foi respondido, objcopy com o flag –redefine-sym é uma boa escolha no Linux. Veja, por exemplo, https://linux.die.net/man/1/objcopy para documentação completa. É um pouco desajeitado porque você está essencialmente copiando toda a biblioteca enquanto faz mudanças e cada atualização requer que esse trabalho seja repetido. Mas pelo menos deveria funcionar.

Para o Windows, carregar dinamicamente a biblioteca é uma solução e uma permanente como a alternativa dlopen no Linux. No entanto, tanto dlopen () quanto LoadLibrary () adicionam código extra que pode ser evitado se o único problema forem nomes duplicados. Aqui, a solução do Windows é mais elegante do que a abordagem objcopy: Basta informar ao vinculador que os símbolos em uma biblioteca são conhecidos por algum outro nome e usar esse nome. Há alguns passos para fazer isso. Você precisa criar um arquivo def e fornecer a tradução do nome na seção EXPORTAÇÕES. Consulte https://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx (VS2015, ele será substituído por novas versões) ou http://www.digitalmars.com/ctg/ctgDefFiles.html (provavelmente mais permanente) para detalhes completos da syntax de um arquivo def. O processo seria criar um arquivo def para uma das bibliotecas e, em seguida, usar esse arquivo def para construir um arquivo lib e vinculá-lo a esse arquivo lib. (Para DLLs do Windows, os arquivos lib são usados ​​apenas para vinculação, não para execução de código.) Consulte Como criar um arquivo .lib quando tiver um arquivo .dll e um arquivo de header para o processo de criação do arquivo lib. Aqui a única diferença é adicionar os aliases.

Para Linux e Windows, renomeie as funções nos headers da biblioteca cujos nomes estão sendo aliasados. Outra opção que deve funcionar seria, nos arquivos referentes aos novos nomes, #define old_name new_name, #include os headers da biblioteca cujas exportações estão sendo alias, e #undef old_name no chamador. Se houver muitos arquivos usando a biblioteca, uma alternativa mais fácil é criar um header ou headers que envolvam o define, includes e undefs e, em seguida, use esse header.

Espero que esta informação tenha sido útil!