Python 3.0 Hacks

第9回 Python3にもC拡張モジュールを─Python3.0でも使える拡張モジュール開発手法の確立

この記事を読むのに必要な時間:およそ 3 分

OpenCVのモジュールを作る!

ctyes-opencvというモジュールがすでに公開されています。それはctypeslibを使っていなさそう? なんですが,結果としてはctypesによるPurePythonモジュールになっていますので「2to3.py」ツールでコンバートすれば動くようになりました。ですが,ここではあえてもう一度今回の手法で構築してみましょう。あらかじめ OpenCV1.0バイナリ版 をインストールしてください。

リスト7のコマンドでビルドできます。

リスト7 build.bat

REM PYTHON3にはPython3.0をインストールしたフォルダを指定してください。
REM OPENCV_DIRには先のOpenCVをインストールしたフォルダを指定。
set PYTHON3=C:\Python30
set PY2TO3=%PYTHON3%\python %PYTHON3%\Tools\Scripts\2to3.py
set PYTHONPATH=
set OPENCV_DIR=C:\Program Files\OpenCV

h2xml cxcore.h -I"%OPENCV_DIR%\cxcore\include" -c -q -o cxcore.xml
h2xml cv.h -I"%OPENCV_DIR%\cxcore\include" -I"%OPENCV_DIR%\cv\include" -c -q -o cv.xml
h2xml highgui.h -I"%OPENCV_DIR%\cxcore\include" -I"%OPENCV_DIR%\otherlibs\highgui" -D WIN32_LEAN_MEAN -c -q -o highgui.xml

xml2py cxcore.xml -lcxcore100.dll -o cxcore.py
xml2py cv.xml -lcv100.dll -o cv.py
xml2py highgui.xml -lhighgui100.dll -o highgui.py
%PY2TO3% -w cxcore.py
%PY2TO3% -w cv.py
%PY2TO3% -w highgui.py

cv,highguiを使ったテスト

リスト8 カメラキャプチャサンプル,ESCキーで終了します。

 1  from cv import *
 2  from highgui import *
 3 
 4  cvNamedWindow('Camera', CV_WINDOW_AUTOSIZE)
 5  capture = cvCreateCameraCapture(0)
 6  while 1:
 7    frame = cvQueryFrame(capture)
 8    cvShowImage ('Camera', frame)
 9    if cvWaitKey(5)&255 == 27:
10      break

OpenGLのモジュールを作る!

glutのヘッダとライブラリを別途入手しておきます。以下のリンクを参考に入手しました。

リスト9にあるコマンドでビルドできます。

リスト9 build.bat

REM PYTHON3にはPython3.0をインストールしたフォルダを指定してください。
set PYTHON3=C:\Python30
set PY2TO3=%PYTHON3%\python %PYTHON3%\Tools\Scripts\2to3.py
set PYTHONPATH=

h2xml GL/gl.h -c -q -o gl.xml
h2xml GL/glu.h -c -q -o glu.xml
h2xml glutdlls37beta/glut.h -c -q -I. -D_STDCALL_SUPPORTED -D_WCHAR_T_DEFINED -o glut.xml

xml2py gl.xml -lopengl32.dll -o gl.py
xml2py glu.xml -lglu32.dll -o glu.py
xml2py glut.xml -lglut32.dll -o glut.py
%PY2TO3% -w gl.py
%PY2TO3% -w glu.py
%PY2TO3% -w glut.py

OpenGLの描画テスト

リスト10 OpenGLの描画テスト

 1  from ctypes import *
 2  from gl import *
 3  from glu import *
 4  from glut import *
 5 
 6  argc = c_long(1)
 7  argv = (c_char_p*1)()
 8  argv[0] = ''
 9  glutInit(argc, argv)
10  glutInitDisplayMode(0)
11  glutInitWindowSize(200,200)
12  glutInitWindowPosition(0,0)
13  glutCreateWindow("Test")
14  glClearColor(0.0, 0.0, 1.0, 1.0)
15 
16  def display():
17    glClear(GL_COLOR_BUFFER_BIT)
18    glutSolidTeapot(0.5)
19    glFlush()
20 
21  def keyboard(ch, param1, param2):
22    if ch==0x1b:
23      quit()
24    else:
25      print(ch, param1, param2)
26 
27  keyboard_cb = CFUNCTYPE(None, c_ubyte, c_int, c_int)(keyboard)
28  glutKeyboardFunc(keyboard_cb)
29  display_cb = CFUNCTYPE(None)(display)
30  glutDisplayFunc(display_cb)
31 
32  glutMainLoop()

図3 リスト10の実行結果

図3 リスト10の実行結果

まとめ

ctypeslibを利用することで,多くのC言語による資産を簡単に取り込めることがわかりました。あと,Linuxなどでも「.dll」ファイルの代わりに「.so」ファイルを利用して同様な手順で拡張モジュールを作ることができるようです。ctypesベースの場合,ダイナミックリンクライブラリのバージョンアップでもヘッダに変更がなければそのまま動作することや, Pythonのバージョンアップにも影響なく動作することは非常に助かります。あと試してませんがPygletやPyOpenGLもctypesベースなので,⁠2to3」ツールで移行できるかも。

欠点としてはC++のライブラリが取り込めないのと,Unicodeをshortアレイ扱いしている定義では本当にshortアレイに変換しなくてはならないところや,ネイティブコードが行っていた橋渡しをPythonコードで行う以上オーバーヘッドが増えていることなどが挙げられます。

しかし,今回の内容だけでもWindowsAPI,SDL,ODE,OpenCV,OpenGLなどがPython3で利用可能になりました。Python3への全面移行は当分先だと思っていましたが,その時期は意外ともうすぐなのかもしれませんね。

著者プロフィール

入江田昇(いりえだ のぼる)

メカ整備やエレクトロニクス系の業務が長く,ロボットに関わることが多い。国のRTミドルウェアプロジェクトでPythonを強く推した張本人。Python/C++を中心に制御ソフトや業務支援ツールなどをよく作成している。自分でブログシステムを構築し,Pythonに関するサイトを運営しながらWeb系の勉強中。最近はFPGAロジックをPythonで書くのが楽しい。