Python – Acessando bibliotecas do Linux com ctypes

A linguagem Python possui muitas bibliotecas, e facilmente conseguimos instalar qualquer uma da internet ou do próprio www.pypi.python.org, que possuirão ‘N’ recursos para protocolos, comunicações, banco de dados, web, mineração de dados, matemática, Gui e entre muitas outras funções.

Vamos conhecer agora um recurso  sensacional para usar no Python, de importar bibliotecas compartilhadas do sistema operacional, no Linux por exemplo as famosas lib*.so e poder usar as funções definidas nas mesmas.

Acessando o link do PyPi sobre ctypes https://docs.python.org/2/library/ctypes.html podemos ver que é bem direto sobre o que você pode fazer e o que ele faz.

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

Uma breve descrição de ctypes, onde surgiu partir da versão 2.5, e com ele conseguimos utilizar uma função em uma biblioteca do sistema, podemos dizer ser um fork da libffi, lib esta que permite chamadas das funções C possam ser feitas em tempo de execução, e isso conseguimos apenas com o Python.

 

Básico do ctypes

Muito bacana isso, vamos fazer um teste com uma biblioteca que tenho certeza que se você possui em seu computador, a libc.so, vamos criar o script ex1_ctypes.py:

Executando:

Você viu como foi simples em poucas linhas usamos o printf() e o time() da libc, o que fizemos foi importar o modulo ctypes, e carregar nossa libc, usando apenas o nome libc.so.6, ou caminho absoluto da biblioteca e usando CDLL ou LoadLibrary, além da grande sacada de carregar e na mesma linha utilizar a função como na linha 17.

 

Pesquisando por funções

E como saber o nome correto das funções, muitas vezes você não esta familiarizado com a estrutura de libs do Linux, mas você pode usar o find_library do ctypes, então vamos ao script ex2_ctypes.py:

Executando:

Que maravilha, não? E ficou claro que caso encontrar a biblioteca retornara com o nome da mesma, caso contrario retorna com None, conforme tentei pesquisar pela ‘abc‘ na linha14.

 

Criando nossa própria biblioteca

Vamos criar uma biblioteca em C básica com apenas duas funções, onde uma irá retornar o nome da função e a próxima um numero randômico, nada que não poderíamos fazer em Python facilmente, mas irei utilizar como exemplo.

Código da nossa biblioteca, mylib.c:

Construindo nossa biblioteca compartilhada:

Criando nosso Python para usar as funções itself() e randomize(int), no ex3_ctypes.py:

Executando nossa aplicação:

Esta imaginando o poder que isso pode lhe oferecer?

 

Acessando variáveis de bibliotecas

Eu não comentei nada sobre a variável global str_name no exemplo anterior, porque iria abordar nesta etapa.

E como você esta pensando, sim, podemos acessar estas variáveis, vamos ao ex4_ctypes:

Executando nosso script:

 

 

Tipos de dados

No exemplo anterior eu deveria fornecer um numero qualquer para minha função randomize(int), e de onde tirei aquele ctype.c_int(), depois usei um tal de ctypes.c_char_p para importar um ponteiro de caracteres, pois é, esta função é uma das responsáveis por tornar compatível os tipos de dados entre C <-> Python, uma relação completa entre os tipos segue abaixo.

ctypes type C type Python type
c_bool _Bool bool (1)
c_char char 1-character string
c_wchar wchar_t 1-character unicode string
c_byte char int/long
c_ubyte unsigned char int/long
c_short short int/long
c_ushort unsigned short int/long
c_int int int/long
c_uint unsigned int int/long
c_long long int/long
c_ulong unsigned long int/long
c_longlong __int64 or long long int/long
c_ulonglong unsigned __int64 or unsigned long long int/long
c_float float float
c_double double float
c_longdouble long double float
c_char_p char * (NUL terminated) string or None
c_wchar_p wchar_t *(NUL terminated) unicode or None
c_void_p void * int/long or None

 

Extras

São muitas as possibilidades e recursos, principalmente com a parte de ponteiros e que merecem e devem ter uma grande atenção.

Algumas dicas extra que posso dar é como exemplo a função create_string_buffer(), caso precisar criar um buffer mutável, onde nos parenteses você fornece o tamanho do buffer, e ele irá retornar um objeto que é um array de c_char, outro recurso é o ctypes.Structure, se você pensou em alguma semelhante com struct em C, pensou certo, onde você pode usar? Vamos ver.

Criando uma nova biblioteca, mystruct.c:

Compilando a biblioteca:

Código Python para usar nossa struct, ex5_ctypes.py:

Executando nossa aplicação python:

Acho que ficou claro o que foi usado no Python para enquadrar com o que fizemos em C certo? Nas referências coloquei um link que aborda só a parte de Structure, vale a pena conferir. Mas e o create_string_buffer? Vamos adaptar um script python pra o buff deste exemplo, no ex6_ctypes.py:

Executando a aplicação:

Vimos um uso pratico do create_string_buffer e confirmamos realmente o que é seu tipo.

Demos uma boa pincelada nos principais recursos do ctypes, mas ele vai muito além.

Gostou de conhecer o ctypes? Incrível não? Caso pretenda usar recomendo fortemente acessar python ctypes, porque existem muitas opções para ser utilizadas e combinadas.

Espero que tenham gostado, até a próxima!

 

Referencias

http://www.pypi.python.org

https://docs.python.org/2/library/ctypes.html

https://docs.python.org/2/library/ctypes.html#structured-data-types

Share Button

CC BY-NC-SA 4.0 Python – Acessando bibliotecas do Linux com ctypes by Cleiton Bueno is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.