[wiki: Interface avec les autres langages de programmation]
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 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 |
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.