5. Construire des extensions C et C++ sur Windows
*************************************************

Cette page explique rapidement comment créer un module d'extension
Windows pour Python en utilisant Microsoft Visual C++, et donne plus
d'informations contextuelles sur son fonctionnement. Le texte
explicatif est utile tant pour le développeur Windows qui apprend à
construire des extensions Python que pour le développeur Unix
souhaitant produire des logiciels pouvant être construits sur Unix et
Windows.

Les auteurs de modules sont invités à utiliser l'approche *distutils*
pour construire des modules d'extension, au lieu de celle décrite dans
cette section. Vous aurez toujours besoin du compilateur C utilisé
pour construire Python ; typiquement Microsoft Visual C++.

Note:

  Cette page mentionne plusieurs noms de fichiers comprenant un numéro
  de version Python encodé. Ces noms de fichiers sont construits sous
  le format de version "XY" ; en pratique, "'X'" représente le numéro
  de version majeure et "'Y'" représente le numéro de version mineure
  de la version Python avec laquelle vous travaillez. Par exemple, si
  vous utilisez Python 2.2.1, "XY" correspond à "22".


5.1. Une approche "recette de cuisine"
======================================

There are two approaches to building extension modules on Windows,
just as there are on Unix: use the "setuptools" package to control the
build process, or do things manually.  The setuptools approach works
well for most extensions; documentation on using "setuptools" to build
and package extension modules is available in Building C and C++
Extensions with setuptools.  If you find you really need to do things
manually, it may be instructive to study the project file for the
winsound standard library module.


5.2. Différences entre Unix et Windows
======================================

Unix et Windows utilisent des paradigmes complètement différents pour
le chargement du code pendant l'exécution. Avant d'essayer de
construire un module qui puisse être chargé dynamiquement, soyez
conscient du mode de fonctionnement du système.

Sur Unix, un fichier objet partagé (".so") contient du code servant au
programme, ainsi que les noms des fonctions et les données que l'on
s'attend  à trouver dans le programme. Quand le fichier est attaché au
programme, toutes les références à ces fonctions et données dans le
code du fichier sont modifiées pour pointer vers les localisations
actuelles dans le programme où sont désormais placées les fonctions et
données dans la mémoire. C'est tout simplement une opération de
liaison.

Sur Windows, un fichier bibliothèque de liens dynamiques (".dll") n'a
pas de références paresseuses. À la place, un accès aux fonctions ou
données passe par une table de conversion. Cela est fait pour que le
code DLL ne doive pas être réarrangé à l'exécution pour renvoyer à la
mémoire du programme ; à la place, le code utilise déjà la table de
conversion DLL, et cette table est modifiée à l'exécution pour pointer
vers les fonctions et données.

Sur Unix, il n'y a qu'un type de bibliothèque de fichier (".a") qui
contient du code venant de plusieurs fichiers objets (".o"). Durant
l'étape de liaison pour créer un fichier objet partagé (".so"), le
lieur peut informer qu'il ne sait pas où un identificateur est défini.
Le lieur le cherchera dans les fichiers objet dans les bibliothèques ;
s'il le trouve, il inclura tout le code provenant de ce fichier objet.

Sur Windows, il y a deux types de bibliothèques, une bibliothèque
statique et une bibliothèque d'importation (toutes deux appelées
".lib"). Une bibliothèque statique est comme un fichier Unix ".a" ;
elle contient du code pouvant être inclus si nécessaire. Une
bibliothèque d'importation est uniquement utilisée pour rassurer le
lieur qu'un certain identificateur est légal, et sera présent dans le
programme quand la DLL est chargée. Comme ça le lieur utilise les
informations provenant de la bibliothèque d'importation pour
construire la table de conversion pour utiliser les identificateurs
qui ne sont pas inclus dans la DLL. Quand une application ou une DLL
est liée, une bibliothèque d'importation peut être générée, qui devra
être utilisée pour toutes les futures DLL dépendantes aux symboles
provenant de l'application ou de la DLL.

Supposons que vous construisez deux modules de chargement dynamiques,
B et C, qui ne devraient pas partager un autre bloc de code avec A.
Sur Unix, vous ne transmettrez pas "A.a" au lieur pour "B.so" et
"C.so" ; cela le ferait être inclus deux fois, pour que B et C aient
chacun leur propre copie. Sur Windows, construire "A.dll" construira
aussi "A.lib". Vous transmettez "A.lib" au lieur pour B et C. "A.lib"
ne contient pas de code ; il contient uniquement des informations qui
seront utilisées lors de l'exécution pour accéder au code de A.

Sur Windows, utiliser une bibliothèque d'importation est comme
utiliser "import spam" ; cela vous donne accès aux noms des spams,
mais ne crée par de copie séparée. Sur Unix, se lier à une
bibliothèque est plus comme "from spam import *" ; cela crée une copie
séparée.

Py_NO_LINK_LIB

   Turn off the implicit, "#pragma"-based linkage with the Python
   library, performed inside CPython header files.

   Ajouté dans la version 3.14.


5.3. Utiliser les DLL en pratique
=================================

Le Python de Windows est construit en Microsoft Visual C++ ; utiliser
d'autres compilateurs pourrait fonctionner, ou pas. Le reste de cette
section est spécifique à MSVC++.

When creating DLLs in Windows, you can use the CPython library in two
ways:

1. By default, inclusion of "PC/pyconfig.h" directly or via "Python.h"
   triggers an implicit, configure-aware link with the library.  The
   header file chooses "pythonXY_d.lib" for Debug, "pythonXY.lib" for
   Release, and "pythonX.lib" for Release with the Limited API
   enabled.

   To build two DLLs, spam and ni (which uses C functions found in
   spam), you could use these commands:

      cl /LD /I/python/include spam.c
      cl /LD /I/python/include ni.c spam.lib

   The first command created three files: "spam.obj", "spam.dll" and
   "spam.lib".  "Spam.dll" does not contain any Python functions (such
   as "PyArg_ParseTuple()"), but it does know how to find the Python
   code thanks to the implicitly linked "pythonXY.lib".

   La seconde commande a créé "ni.dll" (et ".obj" et ".lib"), qui sait
   comment trouver les fonctions nécessaires dans spam, ainsi qu'à
   partir de l'exécutable Python.

2. Manually by defining "Py_NO_LINK_LIB" macro before including
   "Python.h". You must pass "pythonXY.lib" to the linker.

   To build two DLLs, spam and ni (which uses C functions found in
   spam), you could use these commands:

      cl /LD /DPy_NO_LINK_LIB /I/python/include spam.c ../libs/pythonXY.lib
      cl /LD /DPy_NO_LINK_LIB /I/python/include ni.c spam.lib ../libs/pythonXY.lib

   La première commande a créé trois fichiers : "spam.obj", "spam.dll"
   et "spam.lib". "Spam.dll" ne contient pas de fonctions Python
   (telles que "PyArg_ParseTuple()"), mais il sait comment trouver le
   code Python grâce à "pythonXY.lib".

   La seconde commande a créé "ni.dll" (et ".obj" et ".lib"), qui sait
   comment trouver les fonctions nécessaires dans spam, ainsi qu'à
   partir de l'exécutable Python.

Chaque identificateur n'est pas exporté vers la table de conversion.
Si vous voulez que tout autre module (y compris Python) soit capable
de voir vos identificateurs, vous devez préciser
"_declspec(dllexport)", comme dans "void _declspec(dllexport)
initspam(void)" ou "PyObject _declspec(dllexport)
*NiGetSpamData(void)".

Developer Studio will throw in a lot of import libraries that you do
not really need, adding about 100K to your executable.  To get rid of
them, use the Project Settings dialog, Link tab, to specify *ignore
default libraries*.  Add the correct "msvcrt*xx*.lib" to the list of
libraries.
