LangageInterfaces

[wiki: Interface avec les autres langages de programmation]

PageOutline

A ETUDIER :
https://github.com/wjakob/pybind11

Utiliser l’ API C

#!comment
Est-ce que ca existe en Jython ?

Cette interface en langage C donne accès à tout le système Python, et permet d’écrire un module C qui peut être intégré dans un programme principal Python.

Imaginons que l’on veuille donner accès sous Python à la fonction system() du langage C.
On peut créer un module monsys, doté d’une méthode system(), à l’aide du fichier monsys.c suivant :

#!C
#include <Python.h>


static PyObject *
monsys_system(PyObject *self, PyObject *args)
{
const char *commande;
int res;

if (!PyArg_ParseTuple(args, "s", &commande))
return NULL;
res = system(commande);
return Py_BuildValue("i", res);
}

static PyMethodDef MonsysMethods[] = {
{ "system", monsys_system, METH_VARARGS, "Execute a shell command."},
{NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initmonsys(void)
{
(void) Py_InitModule("monsys", MonsysMethods);
}


A l’inverse, on peut également, au sein d’un programme principal écrit en C, lancer et utiliser un interpréteur Python :

#!C
#include <Python.h>


int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
return 0;
}


Utiliser le module ctypes

Ce module fournit des types de données compatible avec le C, ainsi que le moyen de charger des bibliothèques et d’appeler les fonctions qui s’y trouvent, le tout sans écrire la moindre ligne de C.

#!comment


Est-ce que ca existe en Jython ?
Qu'est-ce que ca ne peut pas faire, en comparaison d'une manipulation directe de l'API C ?


Exemple Linux ultra basique :

#!python


import ctypes

# charge la librairie
libc = ctypes.CDLL("libc.so.6")
print libc.printf

# appels de fonction sans argument
print libc.time(None)


Les seuls objets Python qui peuvent être directement passés à des appels de fonction via ctypes :

  • None : passé en tant que pointeur C NULL
  • entiers : passés en tant que type C int, quitte à tronquer la valeur.
  • chaines de caractères : passé en tant que char *
  • chaines de caractères unicode : passé en tant que wchar_t *

Sinon, ctypes définit un ensemble de types servant de passerelles :

ctypes typeC typePython type
c_bool_Boolbool (1)
c_charchar1-character string
c_wcharwchar_t1-character unicode string
c_bytecharint/long
c_ubyteunsigned charint/long
c_shortshortint/long
c_ushortunsigned shortint/long
c_intintint/long
c_uintunsigned intint/long
c_longlongint/long
c_ulongunsigned longint/long
c_longlong__int64 or long longint/long
c_ulonglongunsigned __int64 or unsigned long longint/long
c_floatfloatfloat
c_doubledoublefloat
c_longdoublelong doublefloat
c_char_pchar * (NUL terminated)string or None
c_wchar_pwchar_t * (NUL terminated)unicode or None
c_void_pvoid *int/long or None

Appeler une fonction de la libc :

#!python


>>> printf = libc.printf
>>> printf("Hello, %s\n", "World!")
Hello, World!
14
>>> printf("Hello, %S\n", u"World!")
Hello, World!
14
>>> printf("%d bottles of beer\n", 42)
42 bottles of beer
19
>>> printf("%f bottles of beer\n", 42.5)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2
>>> printf("An int %d, a double %f\n", 1234, c_double(3.14))
An int 1234, a double 3.140000
31


Utiliser un outils d’interfacage automatique

Tout ce qui peut être interfacé avec du C peut donc être interfacé avec CPython, au prix de beaucoup d’effort pour écrire correctement le code qui fait l’interface. Des outils se proposent d’automatiser ces tâches :

Utiliser un interpréteur alternatif

De même, si vous souhaitez interfacer Python et Java, intéressez vous en priorité à Jython, l’implémentation de Python en langage Java.

Références