Python で Btrieve Operation

PSQL というデータベース製品があります。 歴史のあるデータベースで、Wikipedia によると起源は 1980 年代にさかのぼるようです。 このデータベースで特徴的なのは、普通の(SQLを使う) RDB として使える一方 Btrieve API という API を通じて高速にデータの読み書きができるという部分です。 位置づけとしては MySQLHandlerSocket プラグインにちょっと似ているかもしれません。 とは言っても、PSQL の方は Btrieve API しかなかった製品に後から RDB としての機能を追加したという方が正しいようなので、順番が逆ですが。

Btrieve API を使うための C, Visual Basic, Delphi のライブラリーは用意されていますが、Python 用は無かったので作ってみることにしました。

BTRV 関数

Btrieve API は基本的にたった1つの関数(BTRV 関数)を呼び出すことで実行できます。この関数の最初の引数が "オペレーションコード" で、例えばオペレーションコード0は ファイルのオープン、1はファイルのクローズといった具合です。BTRV 関数は実際には(32bit Windows の場合)W3BTRV7.dll という DLL 内にある BTRCALL という関数を呼び出しています。

よって、Python から Btrieve API を使うためには BTRCALL 関数を呼び出せるようにすれば良いということになります。これは ctypes 標準モジュールを使えば簡単に実現できます。 BTRCALL 関数には以下の7つの引数を渡す必要があります。

  • オペレーションコード(unsigned short)
  • ポジションブロック(pointer to byte array)
  • データバッファー(pointer to byte array)
  • データバッファー長(pointer to int)
  • キーバッファー(pointer to byte array)
  • キーバッファー長(unsigned char)
  • キー番号(char)

C のライブラリーのソースを見ると、BTRV 関数は、キーバッファー長に固定で255をセットして BTRCALL 関数を呼び出しているだけのようなので、 Python で BTRV 関数を実装すると以下の様な感じになります。

import ctypes

MAX_KEY_SIZE = 255

BTRCALL = ctypes.windll.w3btrv7.BTRCALL
BTRCALL.restype = ctypes.c_short
BTRCALL.argtypes = [ctypes.c_ushort, ctypes.c_void_p, ctypes.c_void_p,
                    ctypes.POINTER(ctypes.c_int), ctypes.c_void_p,
                    ctypes.c_ubyte, ctypes.c_byte]

def BTRV(operation, posblk, databuf, datalen, keybuf, keynum):
    return BTRCALL(operation, posblk, databuf, datalen, keybuf, MAX_KEY_SIZE, keynum)

BTRV 関数を呼び出すことで基本的にすべての Btrieve API を呼び出せるのですが、さすがにこれだけでは使いづらいので、 便利に使うためのクラスライブラリを準備していきたいと思います。