#
4.1 型どおりのアプローチ

Windows での拡張モジュールのビルドには、Unixと同じように、 `distutils` パッケージを使ったビルド作業の制御と 手動の二通りのアプローチがあります。 distutils によるアプローチはほとんどの拡張モジュールで うまくいきます; `distutils` を使った拡張モジュールの ビルドとパッケージ化については、 Python モジュールの配布 に あります。この節では、C や C++で書かれた Python 拡張モジュール を手動でビルドするアプローチについて述べます。

以下の説明に従って拡張モジュールをビルドするには、インストールされている Python と同じバージョンの Python のソースコードを持っていなければ なりません。また、 Microsoft Visual C++ ``Developer Studio'' が必要になります; プロジェクトファイルは VC++ バージョン 6 向けのものが提供されていますが、以前のバージョンの VC++も 使えます。ここで述べる例題のファイルは、Python ソースコードと 共に配布されており、PC\example_nt\ ディレクトリにあります。

1. 例題ファイルをコピーする
   example_nt ディレクトリは PC ディレクトリのサブディレクトリ になっています。これは PC 関連の全てのファイルをソースコード配布物内の 同じディレクトリに置くための措置です。とはいえ実際には、 example_nt ディレクトリはPC の下では利用できません。 そこで、まずこのディレクトリを一階層上にコピーして、 example_nt が PC および Include と同じ 階層のディレクトリになるようにします。 以降の作業は、移動先の新しいディレクトリ内で行ってください。

2. プロジェクトを開く
   VC++から、 ファイル > ワークスペースを開く ダイアログメニューを選択します (ファイル > 開く ではありません!)。ディレクトリ階層を辿って、example_nt をコピーしたディレクトリ 内のexample.dsw を選択 し、「開く」をクリックします。

3. 例題の DLL をビルドする
   設定が全て正しく行われているか調べるために、ビルドしてみます:

   1. ビルド構成を選びます。このステップは省略できます。 ビルド > アクティブな構成の選択 を選び、 ``example - Win32 リリース'' または ``example - Win32 デバッグ'' を選びます。このステップを飛ばすと、VC++ はデフォルトで デバッグ構成を使います。

   2. DLL をビルドします。デバッグモードなら、 ビルド > example_d.dll のビルド を、 リリースモードなら ビルド > example.dll を選びます。 この操作で。全ての中間ファイルおよび最終ファイルが、上のビルド構成 で選んだ構成に従ってDebug または Release という名前の ディレクトリに生成されます。

4. デバッグモードの DLL をテストする
   デバッグビルドが成功したら、コマンドプロンプトを起動し、 example_nt\Debug ディレクトリに移動して ください。以下のセッション通りにコマンドを実行できるはずです (`C>` は DOS コマンドのプロンプト、`>`>`>` は Python のプロンプトです; ビルド情報や様々なデバッグ出力は、 ここに示したスクリーン出力と一致しないこともあるので注意して下さい):

       C>..\..\PCbuild\python_d
       Adding parser accelerators ...
       Done.
       Python 2.2 (#28, Dec 19 2001, 23:26:37) [MSC 32 bit (Intel)] on win32
       Type "copyright", "credits" or "license" for more information.
       >>> import example
       [4897 refs]
       >>> example.foo()
       Hello, world
       [4903 refs]
       >>>

   おめでとうございます! とうとう初めての Python 拡張モジュールのビルド に成功しましたね。

5. 自分用にプロジェクトを作成する
   プロジェクト用のディレクトリを適当な名前で作成してください。 自作の C ソースコードをディレクトリ内にコピーします。 モジュールのソースコードファイル名は必ずしもモジュール名と 一致している必要はありませんが、初期化関数の名前はモジュール名と 一致していなければなりません -- 初期化関数の名前が `initspam()` なら、モジュールは`spam` という 名前でしか import できません。`initspam()` は 第一引数を `"spam"` にして、`Py_InitModule()` を 呼び出します (このディレクトリにある、最小限の内容が書かれている example.c を手がかりにするとよいでしょう)。 ならわしとして、ファイルはspam.c または spammodule.c という名前にしておきます。 出力ファイル名はリリースモードでは smap.dll や spam.pyd、 デバッグモードではsmap_d.dll や spam_d.pyd、になるはず です (後者は、システムライブラリ spam.dll と、Python インタフェースとなる自作のモジュールとの混同を避けるために 推奨されています) 。

   さて、やり方は二通りあります:

   1. example.dsw と example.dsp をコピーし、 spam.* に名前を変えて、手作業で編集する
   2. 新しくプロジェクトを作成する; 説明は下にあります。

   どちらの場合も、example_nt\example.def を spam\spam.def にコピーして、新たにできた spam.def を編集し、二行目に ``initspam`' が入るように します。 自分で新たなプロジェクトを作成したのなら、ここで spam.def を プロジェクトに追加しておいてください (このファイルはたった二行しか ない目障りなファイルです。.def ファイルを全く無視するという 方法もあり、それには /exprt:initspam を 「プロジェクトのオプション」ダイアログにあるリンク設定のどこかに 手動で追加します)。

6. 新しくプロジェクトを作成する
   ファイル > 新規作成 > プロジェクト ダイアログ を使って、新たなプロジェクト用ワークスペースを作成します。 ``Win32 ダイナミックリンクライブラリ'' を選択し、名前("`spam`") を入れ、「場所」が先ほど作成した spam ディレクトリ下に (Python ビルドツリーの直下のサブディレクトリで、Include および PC と同じディレクトリになるはずです) あることを 確かめます。「作成」をクリックします。

   プロジェクト > 設定 ダイアログを開きます。 ほんのいくつかですが、設定の変更が必要です。 「構成」ドロップダウンリストに「すべての構成」が設定されているか 確かめてください。C/C++ タブを選び、ポップアップメニュー から「プリプロセッサ」カテゴリを選びます。 以下のテキスト:

       ..\Include,..\PC

   を、「追加のインクルードディレクトリ」とラベルされた エントリボックスに入力します

   次に、「リンカ」タブの「入力」カテゴリを選び、

       ..\PCbuild

   を ``追加のライブラリディレクトリ'' と書かれたテキストボックスに 入力します。

   さて、構成ごとに特有の設定をいくつか行う必要があります:

   「構成」 ドロップダウンリストから、``Win32 リリース'' を 選んでください。「リンク」タブをクリックし、「入力」カテゴリを 選んで、「追加の依存ファイル」ボックス内のリストに`pythonXY.lib` を追加します。

   「構成」 ドロップダウンリストから、``Win32 デバッグ'' に切り替え、 「追加の依存ファイル」ボックス内のリストに`pythonXY_d.lib` を追加します。 次に C/C++ タブをクリックして、 ``コード生成'' をカテゴリから 選び、 ``ラインタイムライブラリ'' に対して ``マルチスレッド デバッグ DLL'' を選びます。

   「構成」ドロップダウンリストから ``Win32 リリース'' に切り替えなおし ます。 ``ラインタイムライブラリ'' に対して ``マルチスレッド DLL'' を選びます。

   前の節で述べたspam.def をここで作成しておかねばなりません。 その後、追加 > ファイルをプロジェクトに追加 ダイアログを選びます。「ファイルの種類」を `*.*` にして、 spam.c と spam.def を選び、 OK をクリックします (一つ一つファイルを追加してもかまいません)。

作っているモジュールが新たな型を作成するのなら、 以下の行:

        PyObject_HEAD_INIT(&PyType_Type)

がうまくいかないはずです。そこで:

        PyObject_HEAD_INIT(NULL)

に変更してください。また、以下の行をモジュール初期化関数に加えます:

        MyObject_Type.ob_type = &PyType_Type;

この操作を行う詳しい理由は、 Python FAQ の 第 3 節を参照してください。