5. Building C and C++ Extensions on Windows
*******************************************

This chapter briefly explains how to create a Windows extension module
for Python using Microsoft Visual C++, and follows with more detailed
background information on how it works.  The explanatory material is
useful for both the Windows programmer learning to build Python
extensions and the Unix programmer interested in producing software
which can be successfully built on both Unix and Windows.

Module authors are encouraged to use the distutils approach for
building extension modules, instead of the one described in this
section. You will still need the C compiler that was used to build
Python; typically Microsoft Visual C++.

Notă:

  This chapter mentions a number of filenames that include an encoded
  Python version number.  These filenames are represented with the
  version number shown as "XY"; in practice, "'X'" will be the major
  version number and "'Y'" will be the minor version number of the
  Python release you're working with.  For example, if you are using
  Python 2.2.1, "XY" will actually be "22".


5.1. A Cookbook Approach
========================

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. Differences Between Unix and Windows
=========================================

Unix and Windows use completely different paradigms for run-time
loading of code.  Before you try to build a module that can be
dynamically loaded, be aware of how your system works.

In Unix, a shared object (".so") file contains code to be used by the
program, and also the names of functions and data that it expects to
find in the program.  When the file is joined to the program, all
references to those functions and data in the file's code are changed
to point to the actual locations in the program where the functions
and data are placed in memory. This is basically a link operation.

In Windows, a dynamic-link library (".dll") file has no dangling
references.  Instead, an access to functions or data goes through a
lookup table.  So the DLL code does not have to be fixed up at runtime
to refer to the program's memory; instead, the code already uses the
DLL's lookup table, and the lookup table is modified at runtime to
point to the functions and data.

In Unix, there is only one type of library file (".a") which contains
code from several object files (".o").  During the link step to create
a shared object file (".so"), the linker may find that it doesn't know
where an identifier is defined.  The linker will look for it in the
object files in the libraries; if it finds it, it will include all the
code from that object file.

In Windows, there are two types of library, a static library and an
import library (both called ".lib").  A static library is like a Unix
".a" file; it contains code to be included as necessary. An import
library is basically used only to reassure the linker that a certain
identifier is legal, and will be present in the program when the DLL
is loaded.  So the linker uses the information from the import library
to build the lookup table for using identifiers that are not included
in the DLL.  When an application or a DLL is linked, an import library
may be generated, which will need to be used for all future DLLs that
depend on the symbols in the application or DLL.

Suppose you are building two dynamic-load modules, B and C, which
should share another block of code A.  On Unix, you would *not* pass
"A.a" to the linker for "B.so" and "C.so"; that would cause it to be
included twice, so that B and C would each have their own copy.  In
Windows, building "A.dll" will also build "A.lib".  You *do* pass
"A.lib" to the linker for B and C.  "A.lib" does not contain code; it
just contains information which will be used at runtime to access A's
code.

In Windows, using an import library is sort of like using "import
spam"; it gives you access to spam's names, but does not create a
separate copy.  On Unix, linking with a library is more like "from
spam import *"; it does create a separate copy.

Py_NO_LINK_LIB

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

   Added in version 3.14.


5.3. Using DLLs in Practice
===========================

Windows Python is built in Microsoft Visual C++; using other compilers
may or may not work.  The rest of this section is MSVC++ specific.

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

   The second command created "ni.dll" (and ".obj" and ".lib"), which
   knows how to find the necessary functions from spam, and also from
   the Python executable.

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

   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 "pythonXY.lib".

   The second command created "ni.dll" (and ".obj" and ".lib"), which
   knows how to find the necessary functions from spam, and also from
   the Python executable.

Not every identifier is exported to the lookup table.  If you want any
other modules (including Python) to be able to see your identifiers,
you have to say "_declspec(dllexport)", as in "void
_declspec(dllexport) initspam(void)" or "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.
