19 de maio de 2009

Descobrindo as funções exportadas numa DLL

Imagine a seguinte situação: você tem uma DLL com várias funções exportadas, quer chamar essas funções a partir de um programa seu em Delphi ou C++ mas não consegue descobrir com que nome essas funções foram exportadas e, portanto, não sabe como mapear as funções no seu código.

Já me vi diversas vezes nessa situação, mesmo porque os módulos do ERP da ABC71 são DLLs e a cada operação em um módulo há uma função na DLL. A principal dificuldade é que em bibliotecas escritas em C++ os nomes das funções podem ter sofrido name mangling - toquei nesse assunto em um post sobre como chamar funções C++ no Delphi.

Pesquisando na Internet, localizei uma ferramenta muito boa para saber os nomes exatos das funções e até descobrir se a função desejada foi mesmo exportada. A ferramenta chama-se Dependency Walker. Reproduzo abaixo um pedaço da tela da aplicação que mostra a lista de funções de uma biblioteca que carreguei:
funções exportadasVeja que a primeira coluna indica se a função foi exportada como C, C++ ou através de um índice. Esse índice é o "ordinal" que aparece na segunda coluna. A última coluna traz o nome da função na forma como está exportado, isto é, trata-se do nome que procuramos para passar à função GetProcAddress (API do Windows) ou mapear no Delphi através da declaração external, como no exemplo abaixo.
function index_vlr (vlr: double; indice: smallint;
dt_base: TDateTime; precisao: byte) : double;cdecl;
external 'TPAUX.DLL' name '@index_vlr$qds16System@TDateTimes';

É importante observar que a ferramenta apenas lista os nomes das funções que estão exportadas na biblioteca e que ela não tem como levantar quantos são os parâmetros esperados nem seus tipos de dado - embora seja possível dar um bom chute quando o nome da função agrega name mangling. Portanto, é preciso conhecer bem a biblioteca ou ter uma documentação precisa para obter a informação sobre os parâmetros e tipo de retorno.

A função principal do Dependency Walker é, na verdade, indicar de quais DLLs a DLL indicada depende, isto é, se ela usa funções de outras DLLs - daí o nome de "navegador de dependências". Então, a ferramenta percorre a DLL, verificando quais dependências estáticas estão registradas. Depois, percorre cada uma das dependências encontradas fazendo a mesma coisa, até percorrer todas as DLLs envolvidas. Ao final, tem-se uma lista completa das bibliotecas necessárias para a DLL inicial funcionar corretamente. Isto é bastante útil para determinar quais bibliotecas devem ser incluídas num pacote de instalação, por exemplo.

Para resolver essa questão completamente, no entanto, pode ser necessário usar a opção "Profile". Nessa opção, você carrega um executável (.EXE) e o Dependency Walker tentará monitorar todas as DLL´s usadas pela aplicação, aí incluídas as cargas dinâmicas de DLL (através da função LoadLibrary).

Mais Informações
Dependency Walker, Chamando funções C++ no Delphi (parte 1 e parte 2).

5 comentários :

Unknown disse...

Bom dia! Apesar de estar meio que ressucitando este post, estou com dificuldades para utilizar uma dll, que acredito eu ter sido criada em C, pois a unica documentação que consegui foi aplicação em C utilizando a mesma. Como nao tenho nenhum conhecimento em programação C, pouco conhecimento em Delphi, gostaria de ajuda para desvendar este misterio. Se voce quiser, posso passar a dll com a documentação. Trata-se de uma dll pra trabalhar com um leitor biometrico da Authentec modelo AES3500.

Grato

Roberto Schmitz
schmitz1504@gmail.com

Luís Gustavo Fabbro disse...

Roberto

Que tipo de dificuldade você encontrou pra chamar as funções da DLL? Há outros 2 textos no blog falando sobre como um programa Delphi pode chamar funções de uma DLL C/C++, desde o mapeamento de tipos até a sintaxe para fazer a chamada. Os textos estão em Chamando funções e classes C++ no Delphi e Chamando funções e classes C++ no Delphi - Parte 2.



Algum erro é reportado? Na compilação ou na execução?

[]s

Anônimo disse...

Boa tarde.
Possuo um USBcount50 que é um dispositivo via USB que é utilizado para contar frequencias de sinais. O cd de instalação vem com um software e drivers, porém eu gostaria de saber como eu poderia acessar esse dispositivo para eu fazer a minha propria interface, eu precisaria do que? dlls?
Dentro da pasta do programa "USBcount50" existem 2dll's, CP210xMan.dll e USBcount50Drvr_W32.dll, seriam essas as dlls necessarias e suficientes pra eu conseguir ler os dados do dispostivo dentro do meu código em C problema que não encontro nada sobre a USBcount50Drvr_W32.dll.
http://usbcount50.software.informer.com/
Att.

Luís Gustavo Fabbro disse...

Provavelmente as DLLs que você recebeu já são suficientes pra fazer a comunicação. O que você precisa agora é ter uma documentação das funções dessa DLL para saber a ordem correta de chamada às funções - por exemplo, se primeiro é necessário algum tipo de inicialização interna.

Outra finalidade da documentação é informar a lista de parâmetros de cada função. E, se for o caso, descrever as estruturas de dados manipuladas em cada função.

Dependendo da complexidade das funções, inferir parâmetros e estruturas apenas olhando o conteúdo da biblioteca é tarefa bastante difícil.

[]s

Anônimo disse...

Realmente como não possuo a documentação da DLL crio que seria um trabalho muito díficil. Tentei uma maneira diferente, que foi instalar o python e utilizando pyserial tentar ler a porta e ao rodar a interface do programa do dispositivo eu abria meu codigo em python e lia os dados que estavam passando pelo USB, POREM só agora descobri que o Windows não compartilha portas ao mesmo tempo =(, e meu dispositivo funciona na COM3.
Ainda não sei uma saida pra conseguir os dados exibidos no programa. E creio não conseguir muita ajuda do fabricante.
De qualquer forma muito obrigado pela atenção

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.