chikuchikugonzalezの雑記帳

趣味とか日記とかメモとか(∩゚д゚)

PythonからDXライブラリを使ってみる

たまには技術屋っぽい事も書いておかないと、とか思って最近やってることについて書くなど。

とある方の手伝いで真面目にDirectX触らないといけない自体になりまして*1
とりあえず楽できそうなDXライブラリに手を出してみみました。

が、C/C++な時点でPHPにどっぷり使った私には厳しいかもなぁ(´;ω;`)ブワッとかなってた*2

そんな時に見つけたのがcythonです。

こいつはなんなのかというと、

Cython is a language that makes writing C extensions for the Python language as easy as Python itself. Cython is based on the well-known Pyrex, but supports more cutting edge functionality and optimizations.

The Cython language is very close to the Python language, but Cython additionally supports calling C functions and declaring C types on variables and class attributes. This allows the compiler to generate very efficient C code from Cython code.

This makes Cython the ideal language for wrapping external C libraries, and for fast C modules that speed up the execution of Python code.

http://cython.org/

つまりはPythonっぽい文法でPythonC/C++拡張を作れるというスグレモノ。
こいつぁ使うしかねぇ、ってんでとりあえずDXライブラリをPythonから使えるようにできるかなー、って挑戦したら
3時間でPython用拡張にできることが判明した*3

だいたいこんな風なことをやるとできる。
まずはpxdなるヘッダファイルっぽい何かから

cdef extern from "DxLib.h":
	###############################################
	# 構造体
	###############################################
	ctypedef struct DATEDATA:
		int Year
		int Mon
		int Day
		int Hour
		int Min
		int Sec

	###############################################
	# 関数
	###############################################
	# 必須関数
	int DxLib_Init()
	int DxLib_End()
	int ProcessMessage()

次にコレを使って、python拡張を定義する。一応関数名は同じにしておいた。

from libc.stdlib cimport malloc, free
cimport cdxlib

###########################################
# 必須関数
###########################################
def Init():
	"""DXライブラリの初期化"""
	cdef int result = cdxlib.DxLib_Init()
	if result == 0:
		return True
	else:
		return False

def End():
	"""DXライブラリ使用の終了"""
	cdef int result = cdxlib.DxLib_End()
	if result == 0:
		return True
	else:
		return False

def ProcessMessage():
	"""ウィンドウメッセージ処理関数"""
	cdef int result = cdxlib.ProcessMessage()
	return (result == 0)

ほんでこいつをVisual C++でコンパイルする。今回はこんなMakefileを作った

# Macros
CC=cl.exe
LINK=link.exe
SRCS=dxlib.pyx
GLUE_SRCS=dxlib.cpp
OBJS=dxlib.obj
TARGET=dxlib.pyd
CC_FLAGS=/EHsc /I"E:\Languages\Python27\include" /I"E:\Resources\DxLib\Lib\VC"
LINK_FLAGS=/LIBPATH:"E:\Languages\Python27\libs" /LIBPATH:"E:\Resources\DxLib\Lib\VC" /DLL

# Rules
all: clean $(TARGET)

clean:
	del *.cpp
	del *.pyd
	del *.exp
	del *.lib
	del *.obj

$(TARGET): $(OBJS)
	$(LINK) /OUT:$(TARGET) $(LINK_FLAGS) $<

$(OBJS): $(GLUE_SRCS)
	$(CC) $(CC_FLAGS) /c $<

$(GLUE_SRCS): $(SRCS)
	cython --cplus $<

make allするとdxlib.pydができるので、それをimportして使う。今のところ60fpsは出るっぽいですな。背景なし、キャラ一体だけだけど。

余談:cythonのビルド

cythonの導入に当たっては、ちょいと問題が出た。というのもどうやら想定されている環境がVisual Studio 2008らしい
しかたないので、環境変数VS90COMNTOOLSを環境変数VS100COMNTOOLSと同じ内容で定義することで乗り切った。*4

*1:ギルティギアジャッジメントみたいなアクションゲーだそうで

*2:Visual Studio 2010 Expressとかでやってもいまいちいい構造にできそうもなかった

*3:3割くらいの関数を2日でpyd化した

*4:mt.exeがリソースの埋込みに失敗してたけど、必要なファイルは出来上がってたらしいので、なんどもpython setup.py buildを繰り返した