5. Windows 上での C および C++ 拡張モジュールのビルド
*****************************************************

この章では Windows 向けの Python 拡張モジュールを Microsoft Visual C++
を使って作成する方法について簡単に述べ、その後に拡張モジュールのビルド
がどのように動作するのかについて詳しい背景を述べます。この説明は、
Python 拡張モジュールを作成する Windows プログラマと、Unix と Windows
の双方でうまくビルドできるようなソフトウェアの作成に興味がある Unix プ
ログラマの双方にとって有用です。

モジュールの作者には、この節で説明している方法よりも、distutils による
アプローチで拡張モジュールをビルドするよう勧めます。また、Python をビ
ルドした際に使われた C コンパイラが必要です; 通常は Microsoft Visual
C++です。

注釈:

  この章では、Python のバージョン番号が符号化されて入っているたくさん
  のファイル名について触れます。これらのファイル名は "XY" で表されるバ
  ージョン名付きで表現されます; "'X'" は使っている Python リリースのメ
  ジャーバージョン番号、"'Y'" はマイナーバージョン番号です。例えば、
  Python 2.2.1 を使っているなら、"XY" は実際には "22" になります。


5.1. 型どおりのアプローチ
=========================

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 setuptools による C およ
び C++ 拡張のビルド.  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. Unix と Windows の相違点
=============================

Unix と Windows では、コードの実行時読み込みに全く異なるパラダイムを用
いています。動的ロードされるようなモジュールをビルドしようとする前に、
自分のシステムがどのように動作するか知っておいてください。

Unix では、共有オブジェクト (".so") ファイルにプログラムが使うコード、
そしてプログラム内で使う関数名やデータが入っています。ファイルがプログ
ラムに結合されると、これらの関数やデータに対するファイルのコード内の全
ての参照は、メモリ内で関数やデータが配置されている、プログラム中の実際
の場所を指すように変更されます。これは基本的にはリンク操作にあたります
。

Windows では、動的リンクライブラリ (".dll") ファイルにはぶら下がり参照
(dangling reference) はありません。その代わり、関数やデータへのアクセ
スはルックアップテーブルを介します。従って DLL コードの場合、実行時に
ポインタがプログラムメモリ上の正しい場所を指すように修正する必要はあり
ません; その代わり、コードは常に DLL のルックアップテーブルを使い、ル
ックアップテーブル自体は実行時に実際の関数やデータを指すように修正され
ます。

Unix には、唯一のライブラリファイル形式 (".a") しかありません。 ".a"
ファイルには複数のオブジェクトファイル (".o") 由来のコードが入っていま
す。共有オブジェクトファイル (".so") を作成するリンク処理の段階中に、
リンカは定義場所の不明な識別子に遭遇することがあります。このときリンカ
はライブラリ内のオブジェクトファイルを検索します; もし識別子が見つかる
と、リンカはそのオブジェクトファイルから全てのコードを取り込みます。

Windows では、二つの形式のライブラリ、静的ライブラリとインポートライブ
ラリがあります (どちらも ".lib" と呼ばれています)。静的ライブラリは
Unix における ".a" ファイルに似ています; このファイルには、必要に応じ
て取り込まれるようなコードが入っています。インポートライブラリは、基本
的には特定の識別子が不正ではなく、 DLL がロードされた時点で存在するこ
とを保証するためにだけ使われます。リンカはインポートライブラリからの情
報を使ってルックアップテーブルを作成し、DLL に入っていない識別子を使え
るようにします。アプリケーションや DLL がリンクされるさい、インポート
ライブラリが生成されることがあります。このライブラリは、アプリケーショ
ンや DLL 内のシンボルに依存するような、将来作成される全ての DLL で使う
ために必要になります。

二つの動的ロードモジュール、B と C を作成し、別のコードブロック A を共
有するとします。Unix では、 "A.a" を "B.so" や "C.so"  をビルドすると
きのリンカに渡したりは *しません* ; そんなことをすれば、コードは二度取
り込まれ、B と C のそれぞれが自分用のコピーを持ってしまいます。
Windows では、 "A.dll" をビルドすると "A.lib" もビルドされます。 B や
C のリンクには "A.lib" を渡します。 "A.lib" にはコードは入っていません
; 単に A のコードにアクセスするするために実行時に用いられる情報が入っ
ているだけです。

Windows ではインポートライブラリの使用は "import spam" とするようなも
のです; この操作によって spam の名前にアクセスできますが、コードのコピ
ーを個別に作成したりはしません。Unix では、ライブラリとのリンクはむし
ろ "from spam import *" に似ています;  この操作では個別にコードのコピ
ーを生成します。

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. DLL 使用の実際
===================

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

   二つ目のコマンドでは、 "ni.dll" (および ".obj" と ".lib") ができ、
   このライブラリは spam と 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

   最初のコマンドで、三つのファイル: "spam.obj" 、 "spam.dll"  および
   "spam.lib" ができます。 "Spam.dll" には ("PyArg_ParseTuple()" のよ
   うな) Python 関数は全く入っていませんが、 "pythonXY.lib" のおかげで
   Python コードを見つけることはできます。

   二つ目のコマンドでは、 "ni.dll" (および ".obj" と ".lib") ができ、
   このライブラリは spam と Python 実行形式中の必要な関数をどうやって
   見つければよいか知っています。

全ての識別子がルックアップテーブル上に公開されるわけではありません。他
のモジュール (Python 自体を含みます) から、自作の識別子が見えるように
するには、"void _declspec(dllexport) initspam(void)" や "PyObject
_declspec(dllexport) *NiGetSpamData(void)" のように、
"_declspec(dllexport)" で宣言せねばなりません。

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.
