Empaquetado C / C ++ para Python usando SWIG — Set 1

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

No hay duda de que Numpy, ejecuta una gran cantidad de tareas ? De hecho, las bibliotecas como Numpy no están escritas completamente en Python, algunas partes de la biblioteca están escritas en C, lo que proporciona un mejor rendimiento. Después de escribir el código C, lo envolvemos en código Python, que actúa como una interfaz para esos códigos C. Luego podemos llamar a las funciones de C usando la sintaxis de Python, donde el procesamiento real se realiza en C detrás de escena y el resultado se devuelve como un objeto de Python. En este artículo, veremos cómo crear un contenedor de Python para nuestro programa C en sistemas Linux usando el software SWIG .

Qué es SWIG

En pocas palabras, SWIG — es un compilador que acepta declaraciones de C/C++ y lo envuelve para acceder a esas declaraciones de otros lenguajes, como Python, Tcl, Ruby, etc.
Por lo general, esto no requiere ningún cambio en el código existente y crea una interfaz en un minuto.

Razones para crear un envoltorio

En muchos casos necesitamos envoltorios, los siguientes son —

  • Construcción de una interfaz interpretada para programas C existentes.
  • Crear módulos C de alto rendimiento para lenguajes de secuencias de comandos ‚Äã‚Äã
  • Probar programas C enormes es muy difícil, por lo que escribimos envoltorios en algunos lenguajes de secuencias de comandos ‚Äã‚Äã donde Es muy fácil escribir pruebas. etc

Instalación de SWIG

Para descargar SWIG directamente desde el repositorio de apt, ingrese los siguientes comandos —

sudo apt-get update sudo apt-get install swig 

Escribir un Wrapper usando SWIG

Veamos este fragmento de código en C con dos funciones y una variable global —


/ * archivo: gfg.c * /


# incluir "stdio.h >

# incluir "matemática.h >


// nuestro archivo de cabecera
# include "gfg.h"
# define ll long long


double myvar = 3.4;


// calcular factorial

ll int fact (ll int n)

{

if (n "= 1)

return 1;

else

return (n * hecho (n-1));

}


// encuentra el mod

int my_mod ( int n, int m )

< código clase = "simple"> {

return (n% m);

}

Aquí está nuestro archivo de encabezado — ;


largo largo int fact ( long long < código clase = "color1 negrita"> int n);

int my_mod ( int < /código> n, int m);

Primero tenemos que crear el archivo de interfaz SWIG. Este archivo contiene prototipos de funciones ANSI C y declaraciones de variables. Aquí —

  • La directiva % module especifica el nombre del módulo que usaremos en Python.
  • % {. . % } proporciona un lugar para insertar código adicional, como archivos de encabezado C o declaraciones C adicionales, en el código contenedor generado.
  • La directiva % include nos permite incluir archivos adicionales como archivos de encabezado.

/ * archivo: gfg.i * /


/ * nombre del módulo utilizado * /
% module gfg
% {

/ * Todo lo que hay en este archivo se copia en

archivo contenedor. Incluya el archivo de encabezado C requerido

compile la interfaz * /

# include "gfg.h"

/ * declaración de variable * /

double myvar;

%}


/ * lista explícita de funciones y variables para interacción * /

double myvar;

largo long int < /código> hecho ( largo largo int n1);

int my_mod ( int < /código> m, int n);


/ * o si queremos vincular todas las funciones, podemos simplemente

incluya un archivo de encabezado como este -

% include & quot; gfg.h & quot;

* /

Ahora crearemos el código wrapper usando un comando como

$ swig -python gfg.i 

Este comando genera un código contenedor llamado "gfg_wrap.c" . Estos archivos contienen una versión inflada de nuestra fuente C con un código de manejo de errores diferente, etc. Generaron otro archivo "gfg.py", que es el módulo que estamos importando a nuestro python.


Después de eso, tenemos que generar un código independiente de la posición para usar en la biblioteca compartida compilando "gfg_wrap.c" y "gfg .c" con el siguiente comando:

$ gcc -c -fpic gfg_wrap.c gfg.c -I/use/include/python2.7 

Reemplaza python2 .7 con su versión de Python. Esto creará dos archivos de objeto
"Gfg_wrap.o‚" y "gfg.o‚" . En el comando anterior —

  • generar código independiente de posición (PIC) adecuado para usar en la biblioteca compartida si es compatible con la máquina de destino. Este código accede a todas las direcciones permanentes a través de la tabla de compensación global (GOT)

Nota: si recibe un mensaje de error como las siguientes causas posibles —

  • Es posible que no tenga el ' Python.h ' o
  • Está ingresando la ubicación incorrecta para el ' Python.h ' para el compilador

Para obtener ' Python.h ' tienes que instalar Python-dev, usando el siguiente comando —

$ sudo apt-get install python-dev 

Para encontrar la ruta correcta a Python.h, ejecute el siguiente comando —

$ python -config --cflags 

Esto arrojará algo como esto —

Ahora reemplace la ruta en el comando de compilación con esta para python2.7 o cambie la versión a python3.5 para Python 3.5 .

Ahora, finalmente, tenemos que vincular los archivos de objetos generados para crear un objeto compartido, que es similar a los archivos DLL en Windows. Use el siguiente comando, esto generará un archivo de objeto compartido "_gfg.so"

$ gcc -shared gfg.o gfg_wrap.o -o _gfg.so 

Ahora estamos listos para probar el shell de Python importándolo. Asegúrese de estar en el directorio con este archivo de shell.

> > > importar gfg > > > res = hecho (5) > > > resolución 120 > > > res = mi_mod (5,2) > > > resolución 1 > > > gfg.cvar.myvar 3.4 

Aquí las variables C están disponibles como.

Compilación y enlace usando distutils

< / p>

En lugar de escribir comandos y averiguar qué opciones de compilación se necesitan para compilar archivos, podemos automatizar esto con distutils. Cree como se muestra a continuación —


# Archivo: setup.py


de distutils.core importar configuración, Extensión

# nombre del módulo

nombre = "gfg"


# versión del módulo

versión < /código> = "1.0"


# especifique el nombre de la extensión y los archivos fuente

# requerido para la compilación

ext_modules < código clas s = "palabra clave"> = Extensión (nombre = ’_gfg’ , fuentes = [ " gfg.i " , " gfg.c " ] )


configuración (nombre = nombre,

versión = versión,

ext_modules = [ext_modules])

Ahora escriba los siguientes comandos para compilar e instalar el módulo —

$ python setup.py build_ext --inplace 

Esto debería verse como do algo como esto en la terminal —

Posibles alternativas

Obviamente, SWIG — no es la única forma de crear contenedores, se podrían considerar las siguientes alternativas en función de sus requisitos —

En el siguiente artículo veremos cómo envolver código C++ (OPP)

Enlaces

Este artículo es cortesía de Atul Kumar < /fuerte> . Si es Python.Engineering y le gustaría contribuir, también puede escribir un artículo usando contribuya.python.engineering o publicando un artículo contribuya @ python.engineering. Vea mi artículo que aparece en la página de inicio de Python.Engineering y ayude a otros geeks.

Por favor, publique comentarios si encuentra algún problema o si desea compartir más información sobre el tema discutido arriba.