[1] Integrando Python com C/C++ ~ Introdução

[1] Integrando Python com C/C++ ~ Introdução

Considere um cenário em que, após muito tempo procurando, você encontra uma biblioteca fantástica em C para o que você deseja, porém, ela não tem integração com Python, ou, se tiver, a integração com o Python é limitada. Outro cenário é que você precisa otimizar uma determinada parte do código.

Em ambas situações, uma boa solução é integrar o Python com C/C++. Para isso, na compilação do código em C/C++ criaremos uma shared library. Dois pontos importantes para nós a respeito de uma shared library são:

Considere o seguinte código de exemplo em C:

int adder(int a, int b) {
    return a + b;
}

Esse poderia ser todo o código fonte da nossa shared library. Nela, não precisa nem deve ter uma função main. Agora, precisamos compilar e gerar o nosso arquivo .so - por conversão, arquivos shared libraries tem essa extensão. Há duas formas de compilarmos.

Uma delas é inserir no terminal gcc mytest.c -fPIC -shared -o mytest.so, e então será gerado o arquivo mytest.so. Os parâmetros usados são:

int adder(int a, int b) {
    return a + b;
}

#if __PIC__ == 0
int main() {
    printf("adder(2, 3): %dn", adder(2, 3));
    return 0;
}
#endif

Outra forma de compilarmos é usando o CMake. Basta criar um arquivo chamado CMakeList.txt na mesma pasta do mytest.c e inserir nele add_library(mytest SHARED mytest.c), em seguida usar o comando no terminal cmake . && make. Desse modo, será gerado o arquivo libmytest.so. Repare que o CMake adiciona o prefixo "lib". No decorrer desse manual, consideraremos que o nome do arquivo é "libmytest.so".

Caso queira ter certeza que determinado arquivo é uma shared library, podemos usar o comando file no terminal:

$ file libmytest.so 
libmytest.so: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=d62ea3d8bb728b251f283905a750503a10559d29, not stripped

Agora que temos o nosso arquivo .so, temos que integra-lo no Python. Para isso, usaremos a fantástico ctypes. Com ele, podemos encapsular nossa shared library para torna-la mais facilmente usável.

import ctypes

c_lib = ctypes.CDLL('libmytest.so')
c_lib.adder.restype = ctypes.c_int
c_lib.adder.argtypes = (ctypes.c_int, ctypes.c_int)
print(c_lib.adder(2, 3))

É facilmente entendível esse código de forma impírica, bastando só olhando para entender e pegar a ideia, porém, vamos descrever melhor as três últimas linhas:

Assim, conseguimos criar a ilusão de que estamos acessando uma função no próprio Python, apesar de na realidade estar numa shared library.

Aqui encerra-se a primeira parte no manual "Integrando Python com C/C++". Veja nessa segunda postagem da série como compartilhar os mais diversos tipos de Python e C um com o outro.