Funções executadas automaticamente ao carregar bibliotecas compartilhadas

Ao carregar bibliotecas compartilhadas no Windows, a chamada LoadLibrary() faz com que DllMain na biblioteca seja executado para cada novo processo e a biblioteca de encadeamentos é anexada a cada deattaches da biblioteca de processos e encadeamentos.

Existe mecanismo semelhante para o Mac OS X, Linux e possivelmente outros sistemas operacionais compatíveis com POSIX?

    Você pode definir uma function on-load para uma biblioteca linux usando o mecanismo .init . Isso é o mesmo que especificar o ponto de input do tempo de carregamento para um binário (por exemplo, usando algo diferente de main como ponto de input para um programa).

    Ao vincular usando ld diretamente, você usa o:

     -init  

    ou se você estiver usando o cc / gcc para vincular, use:

     -Wl,-init, 

    Isso é no nível mais simples.

    Editar Para destruidores / finalizadores, você usa o mecanismo .fini . Isso funciona da mesma maneira que a opção init e você usa:

     -fini  

    quando invocar ld . A disponibilidade é limitada à opção -init na plataforma Mac OSX.

    Você também deve ser capaz de usar a syntax __attribute__((constructor)) para o gcc:

     static void con() __attribute__((constructor)); void con() { printf("I'm a constructor\n"); } 

    Qual é provavelmente uma maneira mais portátil do que parafusar com as opções do linker. Todos os construtores devem ser invocados em tempo de carregamento, mas não dependem da ordem de sua boot, o que leva a insanidade e erros não reproduzíveis que custam tempo e esforço para debugging.

    Edit 2 O uso da semântica __attribute__((constructor))/__attribute__((destructor)) é o mecanismo mais preferível para a linguagem de programação C / C ++.

    Para a linguagem de programação D , você deve realmente usar o construtor / destrutor do módulo estático:

     static this() { printf("static this for mymodule\n"); } static ~this() { printf("static ~this for mymodule\n"); } 

    Ou o construtor de class estática:

     class Foo { static this() { printf("static this for Foo\n"); } } 

    Isso é fortemente sugerido na escrita win32 DLLS e na especificação de linguagem relacionada a construtores / destrutores estáticos .

    Editar 3 Você precisará vincular em um .o que exporta rotinas de construtor / destrutor, que permitirá o uso dos inicializadores estáticos. Como tudo o que deve fazer é chamar Runtime.initialize (), isso realmente invoca todos os construtores / destrutores estáticos no código D

    Código stub d para o inicializador (em um arquivo chamado myshared.d ):

     import core.runtime; extern (C) { void attach(); void detach(); } export void attach() { Runtime.initialize(); } export void detach() { Runtime.terminate(); } 

    Crie o .o para este stub:

      dmd -m32 -c myshared.d 

    Verifique os nomes das funções de append / desappend:

     nm myshared.o 

    Mostra (entre outras saídas):

     0000001c S _D8myshared6attachFZv 00000034 S _D8myshared6detachFZv 

    Exemplo de código .c para invocar isso (chamado export.c neste caso), referenciamos os nomes das rotinas exportadas do arquivo my shared.o :

     extern void D8myshared6attachFZv(void); extern void D8myshared6detachFZv(void); void __attach(void) __attribute__((constructor)); void __detach(void) __attribute__((destructor)); void __attach(void) { D8myshared6attachFZv(); } void __detach(void) { D8myshared6detachFZv(); } 

    Observe que as referências de extern void precisam usar o nome desconfigurado da function exportada. Estes devem corresponder ou o código não será vinculado.

    compile o código C usando:

     gcc -m32 -c export.c 

    associe os arquivos .co e .do usando:

     cc -o libmyshared.dylib -m32 -shared myshared.o export.o -lphobos2 

    Supondo que a biblioteca phobos2 esteja em seu caminho de pesquisa de vinculador padrão. O smatterings de opções -m32 para o compilador e vinculador são porque a versão do compilador de D que eu construí localmente suportava apenas 32 bits.

    Isso produz um .dylib que pode ser vinculado a. Parece funcionar com base nos testes limitados que realizei. Parece que o suporte para objects compartilhados / bibliotecas dinâmicas é muito limitado, portanto, há uma boa chance de haver outro obstáculo a ser superado.

    Para que uma function seja executada sempre que a biblioteca compartilhada for carregada ou descarregada, você poderá marcar um construtor e uma function de destruição usando a syntax de atributo específica do GCC:

     __attribute__((constructor)) void init(void) { ... } __attribute__((destructor)) void fini(void) { ... } 

    Como várias partes de um ambiente C dependem das coisas que estão sendo inicializadas no código padrão .init adicionado pelo GCC nos bastidores, o uso direto de -Wl,-init, pode causar a falha do programa.

    Para mais informações, consulte o HOWTO da Libary sobre as funções de construtor e destrutor da Biblioteca .

    O GCC e também o AFAIK suportam os atributos de construtor e destrutor do GCC. Para mais detalhes, veja Como exatamente o __attribute __ ((constructor)) funciona?

    Para C ++ você pode criar uma class e usar seu construtor e destruidor para inicializar a biblioteca.

    Depois, você só precisa definir uma variável para essa class.

    Exemplo de boot de openssl na biblioteca:

     class InitLibrary { public: InitLibrary() { CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use SSL_library_init(); // Initialize OpenSSL's SSL libraries SSL_load_error_strings(); // Load SSL error strings ERR_load_BIO_strings(); // Load BIO error strings OpenSSL_add_all_algorithms(); // Load all available encryption algorithms } ~InitLibrary() { ERR_remove_state(0); CRYPTO_cleanup_all_ex_data(); ENGINE_cleanup(); } }; 

    e adicione somente esta linha no arquivo cpp: InitLibrary InitLib;