Estou sempre fazendo referência a DLLs em meu código C #, mas elas permanecem um mistério que gostaria de esclarecer. Esta é uma espécie de despejo cerebral de perguntas sobre DLLs.
Eu entendo que uma DLL é uma biblioteca vinculada dinamicamente, o que significa que outro programa pode acessar essa biblioteca em tempo de execução para obter "funcionalidade". No entanto, considere o seguinte projeto ASP.NET com Web.dll
e Business.dll
( Web.dll
é a funcionalidade de front end e faz referência Business.dll
a tipos e métodos).
Em que ponto o
Web.dll
link está dinamicamenteBusiness.dll
? Você percebe muitas dificuldades no disco rígido do Windows para tarefas aparentemente pequenas ao usar o Word (etc.) e eu imagino que o Word está desativando e vinculando dinamicamente a funcionalidade de outras DLLs?1a. Além disso, o que carrega e vincula a DLL - o sistema operacional ou alguma estrutura de tempo de execução como a estrutura .NET?
1b. Qual é o processo de "vinculação"? São feitas verificações de compatibilidade? Carregando na mesma memória? O que realmente significa vincular?
O que realmente executa o código na DLL? Ele é executado pelo processador ou há outro estágio de tradução ou compilação antes que o processador compreenda o código dentro da DLL?
2a. No caso de uma DLL construída em C # .NET, o que está executando isso: a estrutura .NET ou o sistema operacional diretamente?
Uma DLL do Linux funciona em um sistema Windows (se tal existir) ou são específicas do sistema operacional?
As DLLs são específicas para uma determinada estrutura? Uma DLL criada com C # .NET pode ser usada por uma DLL criada com, por exemplo, Borland C ++?
4a. Se a resposta a 4 for "não", qual é o objetivo de uma DLL? Por que as várias estruturas não usam seus próprios formatos para arquivos vinculados? Por exemplo: um .exe integrado ao .NET sabe que um tipo de arquivo .abc é algo que pode ser vinculado a seu código.
Voltando à
Web.dll
/Business.dll
exemplo - para obter um tipo de classe de cliente eu preciso de referênciaBusiness.dll
deWeb.dll
. Isso deve significar queBusiness.dll
contém algum tipo de especificação sobre o que uma classe de cliente realmente é. Se eu tivesse compilado meuBusiness.dll
arquivo em, digamos, Delphi: o C # entenderia e seria capaz de criar uma classe de cliente, ou há algum tipo de informação de cabeçalho ou algo que diz "ei, desculpe, você só pode me usar de outra DLL Delphi" ?5a. O mesmo se aplica a métodos; posso escrever um
CreateInvoice()
método em uma DLL, compilá-lo em C ++ e, em seguida, acessá-lo e executá-lo em C #? O que me impede ou me permite de fazer isso?Sobre o assunto de sequestro de DLL, certamente a DLL de substituição (ruim) deve conter as assinaturas e tipos de método exatos como aquele que está sendo sequestrado. Suponho que isso não seria difícil de fazer se você pudesse descobrir quais métodos estão disponíveis na DLL original.
6a. O que em meu programa C # está decidindo se posso acessar outra DLL? Se minha DLL sequestrada contivesse exatamente os mesmos métodos e tipos do original, mas fosse compilada em outro idioma, isso funcionaria?
O que é importação de DLL e registro de DLL?
Respostas:
Em primeiro lugar, você precisa entender a diferença entre dois tipos muito diferentes de DLLs. A Microsoft decidiu usar as mesmas extensões de arquivo (.exe e .dll) com .NET (código gerenciado) e código nativo, no entanto, DLLs de código gerenciado e DLLs nativas são muito diferentes por dentro.
1) No caso do .NET, as DLLs geralmente são carregadas sob demanda quando o primeiro método que tenta acessar qualquer coisa da DLL é executado. É por isso que você pode obter TypeNotFoundExceptions em qualquer lugar do seu código se uma DLL não puder ser carregada. Quando algo como o Word repentinamente começa a acessar muito o HDD, é provável que esteja trocando (obtendo dados que foram trocados para o disco para liberar espaço na RAM)
1a) No caso de DLLs gerenciadas, o framework .NET é o que carrega, o JIT compila (compila o bytecode .NET em código nativo) e vincula as DLLs. No caso de DLLs nativas, é um componente do sistema operacional que carrega e vincula a DLL (nenhuma compilação é necessária porque as DLLs nativas já contêm código nativo).
1b) Linking é quando as referências (por exemplo, chamadas de método) no código de chamada para símbolos (por exemplo, métodos) na DLL são substituídas pelos endereços reais das coisas na DLL. Isso é necessário porque os endereços eventuais das coisas na DLL não podem ser conhecidos antes de serem carregados na memória.
2) No Windows, os arquivos .exe e os arquivos .dll são bastante idênticos. Os arquivos .exe e .dll nativos contêm código nativo (o mesmo material que o processador executa), portanto, não há necessidade de traduzir. Os arquivos .exe e .dll gerenciados contêm bytecode .NET que é primeiro compilado por JIT (traduzido em código nativo).
2a) Depois que o código foi compilado JIT, ele é executado exatamente da mesma maneira que qualquer código.
3) DLLs gerenciadas podem funcionar como estão, contanto que as estruturas em ambas as plataformas estejam atualizadas e quem escreveu a DLL não quebrou a compatibilidade deliberadamente usando chamadas nativas. DLLs nativas não funcionarão da mesma forma, pois os formatos são diferentes (embora o código de máquina interno seja o mesmo, se ambos forem para a mesma plataforma de processador). A propósito, no Linux, "DLLs" são conhecidos como arquivos .so (objeto compartilhado).
4) DLLs gerenciadas são específicas do .NET framework, mas naturalmente funcionam com qualquer linguagem compatível. DLLs nativas são compatíveis, desde que todos usem as mesmas convenções (convenções de chamada (como os argumentos de função são passados no nível de código de máquina), nomenclatura de símbolo, etc)
5) DLLs gerenciadas contêm uma descrição completa de cada classe, método, campo, etc. que contêm. O AFAIK Delphi não oferece suporte ao .NET, então criaria DLLs nativas, que não podem ser usadas no .NET diretamente. Você provavelmente será capaz de chamar funções com PInvoke, mas as definições de classe não serão encontradas. Eu não uso Delphi, então não sei como ele armazena informações de tipo com DLLs. C ++, por exemplo, depende de arquivos de cabeçalho (.h) que contêm as declarações de tipo e devem ser distribuídos com a DLL.
6) Na verdade, não é difícil fazer isso se você puder alternar facilmente a DLL. A assinatura de código pode ser usada para evitar isso. Para que alguém substitua uma DLL assinada, é necessário conhecer a chave de assinatura, que é mantida em segredo.
6a) Funcionaria desde que fosse uma DLL gerenciada, feita com qualquer linguagem .NET.
"Importação de DLL" pode significar muitas coisas, geralmente significa fazer referência a um arquivo DLL e usar coisas nele.
O registro DLL é algo que é feito no Windows para registrar globalmente os arquivos DLL como componentes COM para torná-los disponíveis para qualquer software no sistema.
fonte
Um arquivo .dll contém código compilado que você pode usar em seu aplicativo.
Às vezes, a ferramenta usada para compilar o .dll é importante, às vezes não. Se você pode fazer referência ao .dll em seu projeto, não importa qual ferramenta foi usada para codificar as funções expostas do .dll.
A vinculação acontece em tempo de execução, ao contrário de bibliotecas vinculadas estaticamente, como suas classes, que se vinculam em tempo de compilação.
Você pode pensar em um .dll como uma caixa preta que fornece algo de que seu aplicativo precisa e que você não deseja escrever. Sim, alguém que entende a assinatura do .dll poderia criar outro arquivo .dll com um código diferente dentro dele e seu aplicativo de chamada não poderia saber a diferença.
HTH
fonte
1) Acho que você está confundindo link com carregamento. O link é quando todas as verificações e balanços são testados para ter certeza de que o que é pedido está disponível. No momento do carregamento, partes da dll são carregadas na memória ou trocadas para o arquivo de paginação. Esta é a atividade HD que você está vendo.
A vinculação dinâmica é diferente da vinculação estática, pois na vinculação estática todo o código do objeto é colocado no .exe principal no momento do link. Com a vinculação dinâmica, o código do objeto é colocado em um arquivo separado (dll) e carregado em um momento diferente do .exe.
A vinculação dinâmica pode ser implícita (ou seja, os links do aplicativo com uma biblioteca de importação) ou explícita (ou seja, o aplicativo usa LoadLibrary (ex) para carregar a dll).
No caso implícito, / DELAYLOAD pode ser usado para adiar o carregamento da dll até que o aplicativo realmente precise dela. Caso contrário, pelo menos algumas partes dele são carregadas (mapeadas no espaço de endereço do processo) como parte da inicialização do processo. A dll também pode solicitar que nunca seja descarregada enquanto o processo estiver ativo.
COM usa LoadLibrary para carregar dlls COM. Observe que, mesmo no caso implícito, o sistema está usando algo semelhante a LoadLibrary para carregar a dll na inicialização do processo ou no primeiro uso.
2) Dlls contêm código de objeto exatamente como .exes. O formato do arquivo dll é quase idêntico ao formato de um arquivo exe. Ouvi dizer que há apenas um bit diferente nos cabeçalhos dos dois arquivos.
No caso de uma DLL criada em C # .net, a estrutura .Net está executando-a.
3) DLLs são específicas da plataforma.
4) As DLLs podem interoperar com outras estruturas se um cuidado especial for tomado ou algum código de cola adicional for escrito.
As DLLs são muito úteis quando uma empresa vende vários produtos com recursos de sobreposição. Por exemplo, mantenho uma dll de i / o raster que é usada por mais de 30 produtos diferentes na empresa. Se você tiver vários produtos instalados, uma atualização da dll pode atualizar todos os produtos para novos formatos raster.
5) Dependendo da plataforma, os recursos de uma dll são apresentados de várias maneiras, por meio de arquivos .h, arquivos .tlb ou outras formas em .net.
6) dumpbin / exports e dumbin / import são ferramentas interessantes para usar em .exe e .dlls
fonte