4. Construire des extensions C et C++
*************************************

Une extension C pour CPython est une bibliothèque partagée (Un ".so"
sur Linux, un ".pyd" sur Windows), qui expose une *fonction
d'initialisation*.

Pour pouvoir être importée, la bibliothèque partagée doit pourvoir
être trouvée dans "PYTHONPATH", et doit porter le nom du module, avec
l'extension appropriée. En utilisant *distutils*, le nom est généré
automatiquement.

La fonction d'initialisation doit avoir le prototype :

PyObject *PyInit_modulename(void)

Elle doit donner soit un module entièrement initialisé, soit une
instance de "PyModuleDef". Voir Initializing C modules pour plus de
détails.

Pour les modules dont les noms sont entièrement en ASCII, la fonction
doit être nommée "PyInit_<modulename>", dont "<modulename>" est
remplacé par le nom du module. En utilisant Multi-phase
initialization, il est possible d'utiliser des noms de modules
comptant des caractères non ASCII. Dans ce cas, le nom de la fonction
d'initialisation est "PyInitU_<modulename>", où "modulename" est
encodé avec l'encodage *punyencode* de Python, dont les tirets sont
remplacés par des tirets-bas. En Python ça donne :

   def initfunc_name(name):
       try:
           suffix = b'_' + name.encode('ascii')
       except UnicodeEncodeError:
           suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
       return b'PyInit' + suffix

Il est possible d'exporter plusieurs modules depuis une seule
bibliothèque partagée en définissant plusieurs fonctions
d'initialisation. Cependant pour les importer, un lien symbolique doit
être créé pour chacun, ou un *importer* personnalisé, puisque par
défaut seule la fonction correspondant au nom du fichier est cherchée.
Voir le chapitre *"Multiple modules in one library"* dans la **PEP
489** pour plus d'informations.


4.1. Construire les extensions C et C++ avec *distutils*
========================================================

Des modules d'extension peuvent être construits avec *distutils*, qui
est inclus dans Python. Puisque *distutils* gère aussi la création de
paquets binaires, les utilisateurs n'auront pas nécessairement besoin
ni d'un compilateur ni de *distutils* pour installer l'extension.

Un paquet *distutils* contient un script "setup.py". C'est un simple
fichier Python, ressemblant dans la plupart des cas à :

   from distutils.core import setup, Extension

   module1 = Extension('demo',
                       sources = ['demo.c'])

   setup (name = 'PackageName',
          version = '1.0',
          description = 'This is a demo package',
          ext_modules = [module1])

Avec ce "setup.py" et un fichier "demo.c", lancer :

   python setup.py build

compile "demo.c" et produit un module d'extension nommé "demo" dans le
dossier "build". En fonction du système, le fichier du module peut se
retrouver dans "build/lib.system", et son nom peut être "demo.py" ou
"demo.pyd".

Dans le fichier "setup.py", tout est exécuté en appelant la fonction
"setup". Elle prend un nombre variable d'arguments nommés, dont
l'exemple précédent n'utilise qu'une partie. L'exemple précise des
méta-informations pour construire les paquets, et définir le contenu
du paquet. Normalement un paquet contient des modules additionnels,
comme des modules sources, documentation, sous paquets, etc. Référez-
vous à la documentation de *distutils* dans Distributing Python
Modules (Legacy version) pour en apprendre plus sur les
fonctionnalités de *distutils*. Cette section n'explique que la
construction de modules d'extension.

Il est classique de pré-calculer les arguments à la fonction
"setup()", pour plus de lisibilité. Dans l'exemple ci-dessus,
l'argument "ext_modules" à "setup()" est une liste de modules
d'extension, chacun est une instance de la classe "Extension". Dans
l'exemple, l'instance définit une extension nommée "demo" construite
par la compilation d'un seul fichier source "demo.c".

Dans la plupart des cas, construire une extension est plus complexe à
cause des bibliothèques et définitions de préprocesseurs dont la
compilation pourrait dépendre. C'est ce qu'on remarque dans l'exemple
plus bas.

   from distutils.core import setup, Extension

   module1 = Extension('demo',
                       define_macros = [('MAJOR_VERSION', '1'),
                                        ('MINOR_VERSION', '0')],
                       include_dirs = ['/usr/local/include'],
                       libraries = ['tcl83'],
                       library_dirs = ['/usr/local/lib'],
                       sources = ['demo.c'])

   setup (name = 'PackageName',
          version = '1.0',
          description = 'This is a demo package',
          author = 'Martin v. Loewis',
          author_email = 'martin@v.loewis.de',
          url = 'https://docs.python.org/extending/building',
          long_description = '''
   This is really just a demo package.
   ''',
          ext_modules = [module1])

Dans cet exemple, la fonction "setup()" est appelée avec quelques
autres méta-informations, ce qui est recommandé pour distribuer des
paquets. En ce qui concerne l'extension, sont définis quelques macros
préprocesseur, dossiers pour les en-têtes et bibliothèques. En
fonction du compilateur, *distutils* peut donner ces informations de
manière différente. Par exemple, sur Unix, ça peut ressembler aux
commandes :

   gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o

   gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so

Ces lignes ne sont qu'à titre d'exemple, les utilisateurs de
*distutils* doivent avoir confiance en *distutils* qui fera les appels
correctement.


4.2. Distribuer vos modules d'extension
=======================================

Lorsqu'une extension a été construite avec succès, il existe trois
moyens de l'utiliser.

Typiquement, les utilisateurs vont vouloir installer le module, ils le
font en exécutant :

   python setup.py install

Les mainteneurs de modules voudront produire des paquets source, pour
ce faire ils exécuteront :

   python setup.py sdist

Dans certains cas, des fichiers supplémentaires doivent être inclus
dans une distribution source : c'est possible via un fichier
"MANIFEST.in", voir Specifying the files to distribute pour les
détails.

Si la distribution source a été construite avec succès, les
mainteneurs peuvent aussi créer une distribution binaire. En fonction
de la plateforme, une des commandes suivantes peut être utilisée.

   python setup.py bdist_rpm
   python setup.py bdist_dumb
