12/06/1999
La necesidad de llamar a funciones C desde Python surge con frecuencia en el desarrollo de software. Este artículo explorará las maneras más comunes de lograr esto, enfocándose en las ventajas y desventajas de cada método.

Utilizando la biblioteca ctypes
ctypes es una biblioteca de Python que proporciona una interfaz de función externa (FFI) para llamar a funciones de bibliotecas compartidas (DLLs en Windows, .so en Linux/macOS). Es una solución potente, aunque requiere un conocimiento básico de C y la manipulación de tipos de datos.
Pasos para invocar una función C desde Python usando ctypes:
- Escribir la función C: Crear un archivo (ej: funcion.c ) con la función C que se desea llamar. Esta función debe compilarse en una biblioteca compartida.
- Compilar la función C: Compilar el archivo funcion.c para generar una biblioteca compartida. El comando de compilación puede variar según el sistema operativo, pero un ejemplo para Linux sería:
cc -fPIC -shared -o libfun.so funcion.c - Importar ctypes en Python: En el script Python, importar la biblioteca
ctypes. - Cargar la biblioteca compartida: Usar
ctypes.CDLL("libfun.so")para cargar la biblioteca compilada. Ajustar la ruta si la biblioteca no está en el directorio actual. - Especificar los tipos de argumentos: Indicar los tipos de datos de los argumentos de la función C utilizando
fun.myFunction.argtypes = [...]. - Llamar a la función C: Invocar la función C desde Python utilizando
returnVale = fun.myFunction(NUM), dondeNUMes el argumento.
Ejemplo práctico:
Función C (funcion.c):
int myFunction(int num) { if (num == 0) return 0; else return ((num & (num - 1)) == 0 ? 1 : 0); }Script Python (funcion.py):
import ctypes NUM = 16 fun = ctypes.CDLL("libfun.so") fun.myFunction.argtypes = [ctypes.c_int] returnVale = fun.myFunction(NUM) print(returnVale)Este ejemplo muestra cómo llamar a una función C simple que verifica si un número es una potencia de ctypes ofrece flexibilidad, pero requiere una gestión manual de tipos de datos y puede ser propenso a errores si los tipos no coinciden entre C y Python.

Utilizando PyBind11
PyBind11 es una biblioteca C++ que simplifica la creación de enlaces entre C++ y Python. Es más amigable que ctypes, especialmente cuando se trabaja con clases y estructuras de datos más complejas.

Ventajas de PyBind11 sobre ctypes:
- Mayor facilidad de uso: PyBind11 abstrae la gestión manual de tipos de datos, facilitando la interacción entre C++ y Python.
- Interoperabilidad con NumPy: PyBind11 se integra bien con NumPy, permitiendo la transferencia eficiente de datos entre C++ y Python.
- Soporte para clases C++: Permite exponer clases C++ directamente a Python, lo que facilita la creación de interfaces más complejas.
Pasos para usar PyBind11:
- Instalar PyBind11:
pip install pybind11 - Escribir el código C++: Crear un archivo (ej: mylib.cpp ) con el código C++ que contiene las funciones o clases que se desean exponer a Python.
- Crear el archivo de enlace: Crear un archivo (ej: pywrap.cpp ) que utiliza PyBind11 para generar el módulo Python.
- Compilar: Compilar el código C++ usando CMake o un sistema de construcción similar, enlazando con PyBind11 y generando una biblioteca compartida.
- Importar el módulo en Python: Importar el módulo Python generado desde el script Python.
Ejemplo práctico con PyBind11:
Este ejemplo muestra una clase C++ simple y su enlace a Python utilizando PyBind11:
Código C++ (mylib.h):
#include <Eigen/Dense> #include <cmath> class MyClass { public: void run() { / ...código C++... / } };Código C++ (pywrap.cpp):
#include <pybind11/pybind1h> #include <pybind11/eigen.h> #include "mylib.h" namespace py = pybind11; PYBIND11_MODULE(MyLib, m) { m.doc() = "optional module docstring"; py::class_(m, "MyClass").def("run", &MyClass::run); } Este ejemplo crea una clase MyClassen C++ y expone su método runa Python. PyBind11 gestiona automáticamente la conversión de tipos entre C++ y Python, simplificando el proceso. La compilación requiere un archivo CMakeLists.txtapropiado, que no se incluye aquí por brevedad, pero se puede encontrar en la documentación de PyBind1

Tabla Comparativa:
| Característica | ctypes | PyBind11 |
|---|---|---|
| Facilidad de uso | Baja | Alta |
| Interoperabilidad con NumPy | Requiere gestión manual | Integración directa |
| Soporte para clases C++ | Limitado | Excelente |
| Complejidad | Alta | Moderada |
| Rendimiento | Similar a PyBind11 para funciones simples, puede ser inferior para estructuras complejas | Generalmente mejor para estructuras complejas |
La elección entre ctypes y PyBind11 depende de las necesidades del proyecto. Para funciones simples, ctypes puede ser suficiente. Sin embargo, para proyectos más complejos o cuando se trabaja con clases C++, PyBind11 es la opción más adecuada debido a su mayor facilidad de uso y mejores capacidades de interoperabilidad.
Recuerda que la gestión de la memoria es crucial en ambos casos para evitar fugas de memoria. Asegúrate de liberar la memoria correctamente en el lado C para evitar problemas.
Si quieres conocer otros artículos parecidos a Cómo invocar una librería en python desde c puedes visitar la categoría Libros y Librerías.
