現在進行中、おーぷんMIDIぷろじぇくと、 MIDIData の Python ラッパー作成4
MIDIData の子の親は?
30分前 に存在を知った addressof 関数をさっそく試してみる。
>>> from ctypes import * >>> import mididata._mididata as _mididata >>> import mididata._miditrack as _miditrack >>> data = _mididata.LoadFromSMF('chocho.mid') >>> track1 = _mididata.GetFirstTrack(data) >>> data1 = _miditrack.GetParent(track1) >>> data is data1 False >>> data == data1 False >>> data.contents == data1.contents False >>> # ここまで、失敗の歴史 >>> # ここから、 addressof 実行! >>> addressof(data.contents) == addressof(data1.contents) True >>> _mididata.Delete(data) # 削除は忘れずに
課題の1つが解決。 mididata.MIDIData, miditrack.MIDITrack のデストラクタによる自動メモリ開放は次の手順でできる、かも。
- miditrack.MIDITrack クラス変数に既存インスタンス保持用の辞書を追加。
- miditrack.MIDITrack.__init メソッドにて、前述の辞書に自分のメモリバッファアドレスをキー、自身を値として登録するようにする。
- mididata.MIDIData.__del__ では、前述の辞書から関連する miditrack.MIDITrack のインスタンスをすべて取り出し、それら pointer 変数を None に入れ替える処理を行う。これを開放済みの証とする。探す際のキーとなるトラックらのメモリバッファアドレスは _mididata.GetFirstTrack, _miditrack.GetNextTrack で得る。終わったら _mididata.Delete で自身のメモリを削除する。
- miditrack.MIDITrack のメソッド各種の先頭にて self.pointer が偽値でないことを確認するようにする。実行速度とのトレードオフだがしかたない。
- miditrack.MIDITrack.__del__ の先頭でも self.pointer 確認。偽値でなければ、浮遊トラックであるかどうかを _miditrack.IsFloating で確認。浮いているときのみ _miditrack.Delete で自身のメモリを削除する。
miditrack.MIDITrack, midievent.MIDIEvent の関係も同様の手順でできる、かも。え、結合イベント? あぁ、うん、もう少し考えないとダメだこれは。
浮遊トラック、イベントはプログラマが責任を持って削除してください、という仕様にしてしまえば、 mididata.MIDIData.__del__ で _mididata.Delete して、 miditrack.MIDITrack.__del__, midievent.MIDIEvent.__del__ は実装しない、で解決するのはたしか。
完成予想図
完成形が少しずつ見えてきた。
_mididata のようにアンダーバーから始まるモジュールには DLL の公開関数を直接たたくための関数を集めている。関数名のプレフィックスはモジュール名と被るようにしておいて削る。たとえば MIDIData_Create 関数ならば _mididata モジュールの Create 関数に対応させる。アンダーバーから始まるモジュールのドキュメントの作成予定はほぼなし。くずさんの公式ドキュメント、 Python ctypes のドキュメントの2つを読めば問題ないため。モジュールの docstring や readme とかに命名則とパッケージ構成、オリジナルの URL を書くくらいか。進捗は MIDIInstrumentライブラリ以外のコード作成完了、テストコードは書くと言ったくせにまだ一つもない、ダメだこいつはやくなんとかしないと。
mididata のようなアンダーバーなしのモジュールには Python っぽく使うためのクラスを自作して集める。こちらの docstring は充実させたいところ。進捗は MIDIData, MIDIInstrument ライブラリ以外のコード作成完了、テストコードは(ry