Caros,
Queria um meio para descobrir a interface de uma DLL qualquer. Testei o seguinte exemplo:
Import ctypes
User = ctypes.windll.LoadLibrary(`user32.dll')
F = open(`user32.txt', `w')
For I in dir(user):
f.write(i)
f.write(`\n')
f.close()
Isto não funcionou. Esta DLL tem centenas ou talvez milhares de funções, mas retornaram-me 20 linhas.
Há meio de descobrir o que desejo?
Dependendo da DLL isso pode ser mais ou menos complicado.
DLLs podem ou não ter um certo nível de documentação dos símbolos
exportados. Se a biblioteca tiver sido compilada com informação de debug sua
vida fica mais fácil. Eixstem aplicativos que extraem a informação de debug
em um formato padrão (arquivo .MAP) que pode ser analisado. Mas se a
biblioteca não tiver sido compilada com debug, que é o caso mais comum, é
bem mais complicado. Você pode até achar os entry points mas não saberá nada
sobre parâmetros.
DLLs do Windows (como a user32.dll que você menciona) são razoavelmente bem
documentadas, seja pelo próprio SDK da Microsoft, seja por meio do projeto
Wine.
Você que já programou em Pascal talvez conheça um projeto chamado
"Delphi-Jedi" que se propunha a criar interfaces Delphi para todas as APIs
do Windows. Tem muita coisa feita, mas como Delphi é uma linguagem já em
desuso, a documentação é muito inconsistente. Tem links quebrados e coisas
obsoletas. Mas para estudar talvez seja um bom ponto de partida.
Carlos Ribeiro
2010/1/19 luchyanus <luchyanus@predialnet.com.br>
> Caros,
> Queria um meio para descobrir a interface de uma DLL qualquer. Testei o
> seguinte exemplo:
>
> Import ctypes
>
> User = ctypes.windll.LoadLibrary(`user32.dll')
> F = open(`user32.txt', `w')
> For I in dir(user):
> f.write(i)
> f.write(`\n')
> f.close()
>
> Isto não funcionou. Esta DLL tem centenas ou talvez milhares de funções,
> mas retornaram-me 20 linhas.
> Há meio de descobrir o que desejo?
>
>
>
>
> ------------------------------------
>
> ,----------------------------------------------------------.
> | Antes de enviar um e-mail para o grupo leia: |
> | http://www.pythonbrasil.com.br/moin.cgi/AntesDePerguntar |
> | E se você é usuário do BOL lembre-se de cadastrar o |
> | e-mail do grupo na lista branca do seu sistema anti-spam. |
> `----------------------------------------------------------´Links do
> Yahoo! Grupos
>
>
>
--
Carlos Ribeiro
Consultoria em Projetos
twitter: http://twitter.com/carribeiro
blog: http://rascunhosrotos.blogspot.com
mail: carribeiro@gmail.com
[As partes desta mensagem que não continham texto foram removidas]
Na verdade, esta foi uma pergunta em tese, não uma necessidade real do momento. A User32 é bem documentada, mas a bem dizer, como quase toda a API do Windows, saber sua interface é apenas o primeiro de muitos passos para utilizá-la.
Mas é claro que você tem razão. Para que o dir capture o nome das funções é necessário que ela não esteja completamente encriptada.
Exceto SetConsoleCP e SetConsoleOutputCP para permitir acentuação no console e smdPlaySound para tocar sons, creio que não utilizei mais nada e, ainda assim, creio que estas são da Kernel.
No Python e no Windows, as duas primeiras ainda podem ser utilizadas com Ctypes para garantir que o console seja acentuado, mas enfim, parece que conseguirei mesmo programar interfaces gráficas com IUP. Por isso, esta também é questão superada.
2010/1/19 Carlos Ribeiro <carribeiro@gmail.com>
> (...)
> Você que já programou em Pascal talvez conheça um projeto chamado
> "Delphi-Jedi" que se propunha a criar interfaces Delphi para todas as APIs
> do Windows. Tem muita coisa feita, mas como Delphi é uma linguagem já em
> desuso, a documentação é muito inconsistente. Tem links quebrados e coisas
> obsoletas. Mas para estudar talvez seja um bom ponto de partida.
Estar em desuso não significa que não funciona... ainda mais que a
user32 não mudou sua interface. De qq forma, já existe muito código
feito em Pascal e, como a user32 é muito utilizada, com certeza já
deve existir uma interface Pascal com toda a user32. É só procurar com
calma...
Uma vez tendo o código, fica mais fácil portar para o Python; isso se
já não existir o mesmo código pronto em Python.
Marcos Douglas
O pequeno aplicativo Dependency Walker (Depends.exe) pode mostrar todas as funções exportadas (publicas) de uma dll. Talvez possa usa-lo para logar as funções e chama-las via python.
--- Em python-brasil@yahoogrupos.com.br, "Luciano de Souza" <luchyanus@...> escreveu
> 2010/1/19 luchyanus <luchyanus@...>
> mail: carribeiro@...
>
> [As partes desta mensagem que não continham texto foram removidas]
>
>
>
>
>
> [As partes desta mensagem que não continham texto foram removidas]
>
A User32 foi apenas um exemplo. Na verdade, o meu problema é com IUP, interface gráfica que funciona com C, Lua e Pascal. Neste grupo, indicaram-me o IUPPython, mas infelizmente havia alguns problemas. A biblioteca ainda não tinha sido completamente portada e, além disso, o IUPPython que encontrei era para a versão 2 de IUP. Ocorre que IUP3 possui algumas vantagens que não me atreveria recusar.
Então, pensei: será que não conseguiria eu mesmo portar a biblioteca? Sua interface não é muito extensa e, ademais, ctypes é tão fácil de utilizar.
Pensei e coloquei-me a trabalhar. Com Ctypes, exportei ao menos umas 100 funções. Foi então que surgiu uma dificuldade. IUP é um conjunto de 48 DLLs. A maioria das funções estão em duas delas. ocorre que, embora saiba da existência de algumas funções, por meio do manual de referência, elas não puderam ser encontradas em qualquer das duas.
Assim, ocorreu-me usar "dir" para listar as funções de todas elas, determinando o objeto correto de que deveria herdar determinada função.
Até agora, não fiz nada de extraordinário. Exportei cerca de 100 funções corretamente, mas algumas não pude determinar em que DLL estavão vinculadas. Apesar disso, fiquei muito feliz. Ainda que não tenha feito nada de surpreendente, estar a portar uma biblioteca, para quem se inicia na linguagem, somente pode significar que Python é realmente muito bom.
Mas mesmo quando Python dizia que a função não podia ser encontrada, ainda assim, fiquei a pensar que poderia não a ter encontrado por outro motivo. Primeiramente, verifiquei a capitalização. Depois comecei a ponderar que, de fato, poderia estar declarada em outra DLL. Contudo, pelo que pude ler, minha percepção é de que todas as funções da interface, ou quase sua totalidade, deveriam mesmo estar nestas duas DLLs, sendo as demais chamadas por funções privadas armazenadas nestas duas, mas que referenciam outras DLLs.
Ao fim, creio mesmo que preciso estudar mais para completar o meu trabalho. Não consegui descobrir o formato do parâmetro de uma função que atribuía um callback. Em C, estaríamos diante de um ponteiro para a função. Em Python, não sei como isso ficaria.
Tentei tanto ctypes.cdll quanto ctypes.windll, mas ambas produziram efeito para a maioria das funções, mas não para todas.
Não tenho a interface de cada DLL separadamente, mas tenho a interface do pacote como um todo.
Porque Python possui tipagem dinâmica, não creio que enfrentarei dificuldades com conversão de tipos.
Mas ainda que não tenha o resultado completo, tudo o que consegui transportar para o Python, parece estar a funcionar muito bem.
----- Original Message -----
From: Marcos Douglas
To: python-brasil@yahoogrupos.com.br
Sent: Wednesday, January 20, 2010 11:39 AM
Subject: Re: [python-brasil] Descobrindo a interface de uma DLL
2010/1/19 Carlos Ribeiro <carribeiro@gmail.com>
> (...)
> Você que já programou em Pascal talvez conheça um projeto chamado
> "Delphi-Jedi" que se propunha a criar interfaces Delphi para todas as APIs
> do Windows. Tem muita coisa feita, mas como Delphi é uma linguagem já em
> desuso, a documentação é muito inconsistente. Tem links quebrados e coisas
> obsoletas. Mas para estudar talvez seja um bom ponto de partida.
Estar em desuso não significa que não funciona... ainda mais que a
user32 não mudou sua interface. De qq forma, já existe muito código
feito em Pascal e, como a user32 é muito utilizada, com certeza já
deve existir uma interface Pascal com toda a user32. É só procurar com
calma...
Uma vez tendo o código, fica mais fácil portar para o Python; isso se
já não existir o mesmo código pronto em Python.
Marcos Douglas
[As partes desta mensagem que não continham texto foram removidas]