Python 3.0 Hacks

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

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

SDLのモジュールを作る!

あらかじめSDLをビルドするか,バイナリをダウンロードしましょう(とにかくヘッダ一式とダイナミックリンクライブラリさえあればいい)⁠

上記に置いてあるSDL-devel-1.2.13-mingw32.tar.gzSDL_ttf-devel-2.0.9-VC8.zipのそれぞれから,includeフォルダ以下と*.dllだけを展開しておきます。

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

リスト2 build.bat

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

h2xml SDL.h SDL_ttf.h -c -q -I./SDL -DSDLCALL= -o sdl.xml
xml2py sdl.xml -lSDL.dll -lSDL_ttf.dll -o sdl.py
%PY2TO3% -w sdl.py

コツはxml2pyのとき,作業中のフォルダにダイナミックリンクライブラリを置くことです。h2xmlの「-I」「-D」オプションはgccのものと同じ意味です。⁠-I」がインクルードファイル検索パスで,⁠-D」がマクロ定数定義です

sdl.pyのテスト

利用時は,ダイナミックリンクライブラリをctypesによって発見できるフォルダに置く必要があります。カレントフォルダまたは環境変数Pathに示した場所に置いておけば,ctypesのローダーが発見してくれます。

リスト3 sdl.pyのテスト用コード

 1  from sdl import *
 2 
 3  AVERAGE_NUM = 5
 4 
 5  def main_loop():
 6    frames = [0]*AVERAGE_NUM
 7    event = SDL_Event()
 8    now = SDL_GetTicks()
 9    begin = now
10    fps_suf = None
11    while 1:
12      while SDL_PollEvent(event):
13        if event.type==SDL_QUIT:
14          return
15        elif event.type==SDL_KEYDOWN:
16          if event.key.keysym.sym==SDLK_ESCAPE:
17            return
18      t = SDL_GetTicks()
19      dt = t-now
20      now = t
21      if now22        frames[-1] += 1
23      else:
24        frames.pop(0)
25        frames.append(0)
26        begin = now
27        fps_str = '{0:5.1f}fps'.format(sum(frames)/AVERAGE_NUM).encode('utf-8')
28        fps_suf = TTF_RenderUTF8_Blended(
29          DEFAULT_FONT, fps_str, SDL_Color(255,255,255,0))
30      SDL_FillRect(screen, None, 0)
31      update(dt)
32      if fps_suf:
33        SDL_BlitSurface(fps_suf, None, screen, SDL_Rect(372,424))
34      SDL_UpdateRect(screen, 0, 0, 0, 0)
35      SDL_Delay(0)
36 
37  def update(dt):
38    pass#実際の描画や計算など。
39 
40  SDL_Init(SDL_INIT_VIDEO)
41  TTF_Init()
42 
43  DEFAULT_FONT = TTF_OpenFont('C:\\windows\\fonts\\couri.ttf', 48)
44  dummy = TTF_FontHeight(DEFAULT_FONT) # font check
45 
46  options = SDL_SWSURFACE #| SDL_FULLSCREEN
47  screen = SDL_SetVideoMode(640, 480, 0, options)
48  SDL_WM_SetCaption("Sample", "Sample")
49 
50  main_loop()
51 
52  TTF_CloseFont(DEFAULT_FONT)
53  SDL_Quit()

図2 テスト結果

図2 テスト結果

ODEのモジュールを作る!

あらかじめODEをビルドするか,バイナリをダウンロードしましょう。⁠とにかくヘッダ一式とダイナミックリンクライブラリさえあればいい)

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

リスト4 build.bat

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

h2xml ode/ode.h -Iode-0.11/include -c -q -o ode.xml
xml2py ode.xml -l libode-1.dll -o ode.py
%PY2TO3% -w ode.py

ode.pyのテスト

リスト5 自然落下現象を再現してみる。

 1  from ode import *
 2 
 3  dInitODE2(0)
 4  world = dWorldCreate()
 5  dWorldSetGravity(world,0,0,-9.80665)
 6 
 7  body = dBodyCreate(world)
 8  dBodySetPosition(body, 0.0, 0.0, 10.0)
 9  m = dMass()
10  dMassSetBox(m, 1, 0.1, 0.1, 0.1)
11  dMassAdjust(m, 1.0)
12  dBodySetMass(body, m)
13 
14  for i in range(15):
15    z = dBodyGetPosition(body)[2]
16    print('{0:4.1f}sec z={1:5.2f}'.format(i/10, z))
17    dWorldStep (world,0.1)
18 
19  dWorldDestroy(world);
20  dCloseODE();

リスト6 出力結果

0.0sec z=10.00
0.1sec z= 9.90
0.2sec z= 9.71
0.3sec z= 9.41
0.4sec z= 9.02
0.5sec z= 8.53
0.6sec z= 7.94
0.7sec z= 7.25
0.8sec z= 6.47
0.9sec z= 5.59
1.0sec z= 4.61
1.1sec z= 3.53
1.2sec z= 2.35
1.3sec z= 1.08
1.4sec z=-0.30

10m上空にあった箱を自由落下させると1.4秒後には地面に落下するという結果になりました。理論値は1.43秒なので微妙に誤差がありそうですが……。

著者プロフィール

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

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