Pythonで動くDLLをVCでビルドする方法
きっかけは、
「ピストンコラージュのファイルをPythonで聴けるようにしたいなー」
と思ったことからでした。
(※ピストンコラージュの再生エンジンはDLLで提供されている)
ただ、DLLやら分っていないことが多く、
調査開始から3日間もかかってしまいましたがー。
そんなこんなで苦労して得た情報を惜しげもなく公開します。
よくあるエラー
kenmoがハマったエラーはこんな感じです。
fatal error LNK1104: コンパイラは、ファイル 'python23_d.lib' を開くことができません。
ビルドの構成が「Debug」だと、デバッグ用のlibを見にに行くためこのようなエラーが出るみたいです。
なのでビルドの構成を「Release」にすれば解決です。
あと、ビルドはできたものの動かないケース。
Traceback (most recent call last):
File "c:\work\vsproj\test\release\test.py", line 1, in ?
import test
ImportError: dynamic module does not define init function (inittest)
これにはいくつか原因があります。
- cppファイルをビルドする場合に初期化メソッドに「extern "C"」がない場合
- ヘッダファイルがない
- 初期化関数に「__declspec(dllexport)」がない
1は、Pythonは直接にはCのコードしか呼び出せないためです。
なので、初期化メソッドには「extern "C"」をつけなければいけません。
2は、DLLはヘッダファイルがないとダメみたいです。
原因は良く分かりませんがー。
3は、DLLの決まりごとみたいです。
手順
プロジェクトの作成
- 新しいプロジェクトの作成->Win32プロジェクト(ここでは「test」というプロジェクト名にします)
- アプリケーションウィザードで「アプリケーションの設定」を選び、アプリケーションの種類を「DLL」、追加のオプションで「空のプロジェクト」を選びます。
ビルドの設定
- ビルド->構成マネージャー->アクティブソリューション構成を「Release」に
これをやらないと「fatal error LNK1104: コンパイラは、ファイル 'python23_d.lib' を開くことができません。」というエラーが出ます。
(自分でPythonをビルドした人は問題ないのですが)
プロジェクトの設定
- プロジェクト->testのプロパティ、でプロパティページを開く
- C/C++->全般->追加のインクルードディレクトリに「C:\Python23\include」を設定(2.4を使っていれば「C:\Python24\include」)
- C/C++->コード生成->ランタイムライブラリを「マルチスレッド DLL (/MD)」に設定
- リンカ->全般->追加のライブラリディレクトリに「C:\Python23\libs」を設定(2.4を使っていれば「C:\Python24\libs」)
あと、出力ファイルの拡張子が「.dll」というのが気に入らなければ、
- リンカ->全般->出力ファイルを「$(OutDir)/test.dll」から「$(OutDir)/test.pyd」に変更
です。
ただ、これは必須ではないですがー。
テスト用ソースコード
例えばこのようなtest.h/test.cppをプロジェクトに追加します。
<test.h>
#include "Python.h" // これがないとダメみたい #define DLLEXPORT __declspec(dllexport) extern "C" DLLEXPORT void inittest();
<test.cpp>
#include "test.h" // "Hello .."という文字列を返す関数 static PyObject* test_hello(PyObject* self) { return Py_BuildValue("s", "Hello! This is test."); } // 関数テーブル static PyMethodDef testmethods[] = { // メソッド"hello"の実体は「test_hello」で引数はなし {"hello", (PyCFunction)test_hello, METH_NOARGS}, {NULL}, }; // 初期化メソッド(init+モジュール名でなければならない) extern "C" void inittest() { // "test"モジュールを初期化 Py_InitModule("test", testmethods); }
ビルド
F7キーでビルドすると、Releaseフォルダに「test.dll」(もしくはtest.pyd)ができます。
Pythonからの呼び出し
Releaseフォルダにコマンドプロンプトを移動して、Pythonを実行し、
>>>import test >>>test.hello() Hello! This is test.
と出ればOKです。
これでPythonから、libBulletMLとかT'SoundSystemとかをいじれるようになります。
おおお、夢が膨らみますねー。
参考リンク
これらのページがなければ、なんともなりませんでした。
インターネットは素晴らしいなー、などと今更思いました。
追記
現在無料でMSのサイトから手に入る、
「Visual C++ 2005 Express Edition」
「Windows Platform SDK」
をインストールすることにより、同一の手順でビルドできることを確認しましたー。
(※インストール参考ページ「Visual C++ Express Editionを使ってみる(Windows Platform SDK編)」)
Pythonネタ
DLLの調査中に見つけたPythonネタ。
http://d.hatena.ne.jp/Wacky/20060304/1141471840
組込み型がクラスでないのは美しくないなどとあげつらっていた連中がかつての主張を過去形に直している様も最高だ
最近kenmoは、「オブジェクト指向」について疑問を持っていまして、、。
継承でクラスの階層ツリーがポコポコ作られたり、
委譲でクラスのネストが深くなるのが、
どうもエレガントじゃないなー、などと思っています。
そう考えるとオブジェクトがモジュールで区切られて、
「関数プログラミング」ができるPythonはなかなか有利ではないのかと思ったり思わなかったり。
他にも
空白文字をならべたインデントの論理性がbegin/endと共に括弧を吹き飛ばすのが好きだ 偏見に満ちた多言語ユーザどもが可読性に魅せられて虜になった時など心がおどる
とか、
哀れな初心者達が市販の入門書を手にして健気にも勉強してきたのを lambdaスキーと内包表現スキーの一行野郎が「はじパイ」仕込みの達成感もろとも木端微塵に粉砕した時など絶頂すら覚える
に共感を覚えてるkenmoが怖いです(´∀`;
なんか、874氏の発言がHIPHOPの歌詞みたいでカッコいいしー。