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.


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++.

Lorsque vous créez des DLL sur Windows, vous devez transmettre
"pythonXY.lib" au lieur. Pour construire deux DLL, spam et ni (qui
utilisent des fonctions C trouvées dans spam), vous pouvez utiliser
ces commandes :

   cl /LD /I/python/include spam.c ../libs/pythonXY.lib
   cl /LD /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.
