Uma biblioteca de vínculo dinâmico é uma coleção de procedimentos e funções que podem ser chamadas por aplicativos e outras DLLs. Ela contém código ou recursos públicos. Como o código DLL usa tecnologia de compartilhamento de memória, o Windows também concede à DLL algumas permissões mais altas em alguns lugares, de modo que a DLL pode implementar algumas funções que não podem ser alcançadas por programas comuns, como implementar Windows HOOK, ISAPI, etc. Ao mesmo tempo, o DLL também fornece uma maneira conveniente de compartilhamento de código entre diferentes linguagens. Portanto, DLL é amplamente utilizado em programação. Este artigo apresentará como criar e usar DLL em Delphi.
um. Mecanismo de compartilhamento de memória da biblioteca DLL
Do ponto de vista do uso, DLL e unidade são muito semelhantes. Ambas podem ser chamadas por outros módulos do projeto, mas existem diferenças em seus mecanismos internos de implementação. Se um módulo de programa usa uma instrução usa para fazer referência a uma unidade, quando o compilador compila o módulo, ele o compilará junto com a unidade e vinculará o código executável compilado ao módulo do programa. procedimentos e funções na unidade referenciada. Quando a mesma unidade é referenciada por vários projetos, cada projeto contém o código executável da unidade. Quando vários projetos contendo a unidade são executados ao mesmo tempo, o código executável da unidade será atualizado várias vezes com projetos diferentes. na memória, causando um desperdício de recursos de memória. DLL é diferente. Mesmo que seja chamada por um determinado projeto, ela ainda é independente após a compilação. Ou seja, após a compilação, uma biblioteca DLL forma um arquivo executável separado e não está conectada a nenhum outro arquivo executável. A biblioteca DLL não está subordinada a um projeto específico. Quando vários projetos chamam a mesma biblioteca DLL, apenas o primeiro projeto transfere a biblioteca DLL para a memória. Os outros projetos não transferem repetidamente a mesma biblioteca DLL para a memória, mas lêem da memória. mesma área de memória compartilhada. Além disso, o código de execução da DLL é transferido dinamicamente durante a execução do programa, em vez de ser transferido para a memória junto com todo o projeto quando o programa está em execução. Isso pode eliminar as desvantagens causadas pela unidade de que o mesmo código ocupa memória em vários locais.
2. Criação de biblioteca DLL em Delphi
No ambiente Delphi, escrever uma DLL não é muito diferente de escrever uma aplicação geral. Na verdade, a gravação de DLL funciona como o corpo principal da DLL e não requer nenhum outro meio especial, exceto diferenças na memória e no gerenciamento de recursos.
O formato dos arquivos gerais do projeto é:
Título do projeto do PROgrama;
cláusula de uso;
Corpo do programa
O formato dos arquivos de projeto DLLs é:
título do projeto da biblioteca;
cláusula de uso;
cláusula de exportação;
Corpo do programa
Existem duas diferenças principais entre eles:
1. Geralmente, o cabeçalho dos arquivos de projeto usa a palavra-chave do programa, enquanto o cabeçalho dos arquivos de projeto DLL usa a palavra-chave da biblioteca. Palavras-chave diferentes dizem ao compilador para gerar diferentes arquivos executáveis. A palavra-chave do programa é usada para gerar um arquivo .exe e a palavra-chave da biblioteca é usada para gerar um arquivo .dll;
2. Se a DLL desejar exportar funções ou procedimentos para uso por outros aplicativos, essas funções ou procedimentos deverão ser listados na cláusula exports. Estas funções ou procedimentos devem ser compilados usando a diretiva de compilação de exportação.
Selecione o novo item... no arquivo do menu principal do Delphi, clique duas vezes no ícone da DLL na janela pop-up e a estrutura do módulo de origem da DLL será fornecida automaticamente, como segue:
Bibliotecaprojeto1;
{...anotação...}
usa
SysUtils, Classes;
começar
fim.
Em seguida, você pode adicionar as definições dos procedimentos e funções que deseja implementar na DLL entre USES e Begin, e usar export e exports para exportá-los para que outros módulos possam referenciá-los. é usado para inicializar variáveis DLL. Ressalta-se que mesmo que não haja código de inicialização, o início e o fim não podem ser omitidos, como no exemplo a seguir:
bibliotecaminmax;
functionMin(X,Y:Inteiro):Inteiro;exportar;
começar
ifX<YthenMin:=XelseMin:=Y;
fim;
functionMax(X,Y:Inteiro):Inteiro;exportar;
começar
ifX>YthenMax:=XelseMax:=Y;
fim;
exportações
Miniíndice1,
Maxíndice2;
começar
fim.
Após compilar e salvar como minmax.DLL, um arquivo de biblioteca DLL é formado.
Acesso a três bibliotecas DLL
Existem duas maneiras de acessar a biblioteca DLL, uma é referência estática e a outra é referência dinâmica.
Carregar uma DLL usando um método de referência estática requer duas coisas: criar uma unidade de entrada para a biblioteca DLL e usar USES para conectar a unidade de entrada ao módulo do programa que usa as funções DLL. A única diferença entre a unidade de entrada criada para a biblioteca DLL e a unidade comum é que os procedimentos e funções declarados em sua interface não fornecem o código de implementação real em sua parte de implementação. Em vez disso, a palavra-chave externa é usada para declarar os procedimentos e. funções Os detalhes de implementação são delegados a módulos DLL externos.
A sintaxe para usar o comando externo é a seguinte:
procedimento/função procedimento/nome da função; nome do módulo externalDLL;
A seguir está o arquivo fonte da unidade de entrada testdll.pas escrito para a biblioteca minmax.DLL criada acima. A partir dele, podemos ver algumas diferenças entre a unidade de entrada e a unidade geral.
unittestdll;
interface
usa
funçãoMin(X,Y:Inteiro):Inteiro;
functionMax(X,Y:Inteiro):Inteiro;
implementação
functionMin;externo'minmax.DLL';
functionMax;externo'minmax.DLL';
fim.
Se um aplicativo quiser chamar uma função em minmax.DLL, ele só precisará adicionar a unidade testdll à sua instrução uses.
O carregamento dinâmico de uma DLL requer três funções de API do Windows. Loadlibrary, Freelibrary e GetprocAddress. A função loadlibrary é usada para carregar a biblioteca DLL. Seu formato de chamada é o seguinte:
functionloadlobrary(DLLfileName:Pchar):THandle:
Quando uma biblioteca DLL não é mais necessária, a função FreeLibrary deve ser chamada para liberá-la e liberar recursos valiosos de memória. O formato de chamada é o seguinte:
procedimentoFreeLibrary(Libmodule:THandle)
Libmodule é o identificador da biblioteca DLL obtido pela chamada LoadLibrary. No segmento do programa entre carregar uma biblioteca DLL com a função loadlobrary e chamar FreeLibrary para liberar a biblioteca DLL, você pode usar os procedimentos e funções da biblioteca DLL. O método específico de uso é: usar a função GetprocAddress para obter o endereço de. a função na biblioteca DLL passe-a para uma variável de função no programa e, em seguida, use a variável para chamar a função DLL. A função GetprocAddress é declarada da seguinte forma,
functionGetprocAddress(Libmodule:THandle:procname:pchar):TFarProc:
Conforme mostrado no exemplo a seguir:
tipo
TTimeRec=registro
Segundo:Inteiro;
Minuto:Inteiro;
Hora:Inteiro;
fim;
TGetTime=procedimento(varTime:TTimeRec);
Thandle=Inteiro;
var
Tempo:TTimeRec;
Alça: alça;
GetTime:TGetTime;
...
começar
Identificador:=LoadLibrary('DATETIME.DLL');
ifHandle<>0então
começar
@GetTime:=GetProcAddress(Handle,'GetTime');
if@GetTime<>nilthen
começar
GetTime(Tempo);
comTimedo
WriteLn('Ahoraé',Hora,':',Minuto,':',Segundo);
fim;
FreeLibrary(Alça);
fim;
fim;
Ao chamar a biblioteca de vínculo dinâmico, observe que a biblioteca de vínculo dinâmico necessária deve estar no mesmo diretório que o aplicativo ou no diretório WindowsSystem.
Bibliotecas de vínculo dinâmico são uma forma importante de organizar programas no Windows. O uso de bibliotecas de vínculo dinâmico pode proteger bastante o trabalho realizado pelos usuários em diferentes ferramentas de desenvolvimento e em diferentes períodos e melhorar a eficiência da programação.