5.5。 WindowsでのCおよびC ++拡張機能の構築
この章では、Microsoft Visual C ++を使用してPython用のWindows拡張モジュールを作成する方法を簡単に説明し、その仕組みに関するより詳細な背景情報を示します。 説明資料は、Python拡張機能の構築を学習しているWindowsプログラマーと、UnixとWindowsの両方で正常に構築できるソフトウェアの作成に関心のあるUnixプログラマーの両方に役立ちます。
モジュールの作成者は、このセクションで説明されているものではなく、distutilsアプローチを使用して拡張モジュールを構築することをお勧めします。 Pythonのビルドに使用されたCコンパイラが引き続き必要です。 通常、Microsoft Visual C ++です。
ノート
この章では、エンコードされたPythonバージョン番号を含むいくつかのファイル名について説明します。 これらのファイル名は、XY
として示されているバージョン番号で表されます。 実際には、'X'
がメジャーバージョン番号になり、'Y'
が使用しているPythonリリースのマイナーバージョン番号になります。 たとえば、Python 2.2.1を使用している場合、XY
は実際には22
になります。
5.1。 クックブックアプローチ
Unixの場合と同様に、Windowsで拡張モジュールをビルドするには2つのアプローチがあります。 distutils パッケージを使用してビルドプロセスを制御するか、手動で実行します。 distutilsアプローチは、ほとんどの拡張機能でうまく機能します。 distutils を使用して拡張モジュールをビルドおよびパッケージ化する方法に関するドキュメントは、 Pythonモジュールの配布(レガシーバージョン)にあります。 本当に手動で行う必要がある場合は、プロジェクトファイルを調べておくと役立つ場合があります。 :source: `winsound ` 標準ライブラリモジュール。
5.2。 UnixとWindowsの違い
UnixとWindowsは、コードの実行時ロードにまったく異なるパラダイムを使用します。 動的にロードできるモジュールを構築する前に、システムがどのように機能するかを知っておいてください。
Unixでは、共有オブジェクト(.so
)ファイルには、プログラムで使用されるコードと、プログラムで検出されると予想される関数とデータの名前が含まれています。 ファイルがプログラムに結合されると、ファイルのコード内のこれらの関数とデータへのすべての参照は、関数とデータがメモリに配置されるプログラム内の実際の場所を指すように変更されます。 これは基本的にリンク操作です。
Windowsでは、ダイナミックリンクライブラリ(.dll
)ファイルにぶら下がっている参照はありません。 代わりに、関数またはデータへのアクセスはルックアップテーブルを経由します。 したがって、プログラムのメモリを参照するために、実行時にDLLコードを修正する必要はありません。 代わりに、コードはすでにDLLのルックアップテーブルを使用しており、ルックアップテーブルは実行時に関数とデータを指すように変更されます。
Unixでは、複数のオブジェクトファイル(.o
)からのコードを含むライブラリファイル(.a
)のタイプは1つだけです。 共有オブジェクトファイル(.so
)を作成するためのリンク手順中に、リンカは識別子が定義されている場所がわからないことに気付く場合があります。 リンカは、ライブラリ内のオブジェクトファイルでそれを探します。 見つかった場合は、そのオブジェクトファイルのすべてのコードが含まれます。
Windowsには、静的ライブラリとインポートライブラリ(どちらも.lib
と呼ばれます)の2種類のライブラリがあります。 静的ライブラリは、Unix .a
ファイルのようなものです。 必要に応じて含めるコードが含まれています。 インポートライブラリは基本的に、特定の識別子が有効であり、DLLがロードされるときにプログラムに存在することをリンカに保証するためにのみ使用されます。 そのため、リンカはインポートライブラリの情報を使用して、DLLに含まれていない識別子を使用するためのルックアップテーブルを作成します。 アプリケーションまたはDLLがリンクされると、インポートライブラリが生成される場合があります。これは、アプリケーションまたはDLLのシンボルに依存する将来のすべてのDLLで使用する必要があります。
コードAの別のブロックを共有する必要がある2つの動的ロードモジュールBとCを構築しているとします。 Unixでは、はA.a
をB.so
およびC.so
のリンカーに渡さない。 これにより、2回含まれるため、BとCはそれぞれ独自のコピーを持ちます。 Windowsでは、A.dll
をビルドするとA.lib
もビルドされます。 do はA.lib
をBとCのリンカーに渡します。 A.lib
にはコードが含まれていません。 実行時にAのコードにアクセスするために使用される情報が含まれているだけです。
Windowsでは、インポートライブラリを使用することは、import spam
を使用することと似ています。 スパムの名前にアクセスできますが、個別のコピーは作成されません。 Unixでは、ライブラリとのリンクはfrom spam import *
に似ています。 別のコピーを作成します。
5.3。 DLLの実際の使用
WindowsPythonはMicrosoftVisual C ++に組み込まれています。 他のコンパイラを使用すると、機能する場合と機能しない場合があります(Borlandは機能しているようですが)。 このセクションの残りの部分はMSVC ++固有です。
WindowsでDLLを作成するときは、pythonXY.lib
をリンカに渡す必要があります。 2つのDLL、spamとni(spamにあるC関数を使用)を作成するには、次のコマンドを使用できます。
cl /LD /I/python/include spam.c ../libs/pythonXY.lib
cl /LD /I/python/include ni.c spam.lib ../libs/pythonXY.lib
最初のコマンドは、spam.obj
、spam.dll
、spam.lib
の3つのファイルを作成しました。 Spam.dll
にはPython関数( PyArg_ParseTuple()など)は含まれていませんが、pythonXY.lib
のおかげでPythonコードを見つける方法はわかっています。
2番目のコマンドはni.dll
(および.obj
と.lib
)を作成しました。これは、スパムおよびPython実行可能ファイルから必要な関数を見つける方法を知っています。
すべての識別子がルックアップテーブルにエクスポートされるわけではありません。 他のモジュール(Pythonを含む)が識別子を認識できるようにする場合は、void _declspec(dllexport) initspam(void)
またはPyObject _declspec(dllexport) *NiGetSpamData(void)
のように、_declspec(dllexport)
と言う必要があります。
Developer Studioは、実際には必要のない多くのインポートライブラリを投入し、実行可能ファイルに約100Kを追加します。 それらを取り除くには、[プロジェクト設定]ダイアログの[リンク]タブを使用して、デフォルトライブラリを無視するを指定します。 正しいmsvcrtxx.lib
をライブラリのリストに追加します。