銀月の符号

Python 使い見習いの日記・雑記

現在進行中、おーぷん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 のデストラクタによる自動メモリ開放は次の手順でできる、かも。

  1. miditrack.MIDITrack クラス変数に既存インスタンス保持用の辞書を追加。
  2. miditrack.MIDITrack.__init メソッドにて、前述の辞書に自分のメモリバッファアドレスをキー、自身を値として登録するようにする。
  3. mididata.MIDIData.__del__ では、前述の辞書から関連する miditrack.MIDITrack のインスタンスをすべて取り出し、それら pointer 変数を None に入れ替える処理を行う。これを開放済みの証とする。探す際のキーとなるトラックらのメモリバッファアドレスは _mididata.GetFirstTrack, _miditrack.GetNextTrack で得る。終わったら _mididata.Delete で自身のメモリを削除する。
  4. miditrack.MIDITrack のメソッド各種の先頭にて self.pointer が偽値でないことを確認するようにする。実行速度とのトレードオフだがしかたない。
  5. 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