Raspberry Pi によるイーサネットコンバータ (2) 設定

前回の記事で準備ができたので、

  • 有線ポートのIPアドレスを固定
  • 有線ポート側でDHCPサーバーを稼動
  • 有線ポート・無線ポート間でルーティング(NAPT)を設定

をする。 Ubuntu PCをルータ代わりにして、新しくLANを構築してみる を参考にするが、OSの違い等を考慮して少し手順を変更している。

IPアドレス固定

現在のバージョンのRaspbianでは /etc/network/interfaces ではなく /etc/dhcpcd.conf で設定するようだ。以下の通り設定する。

interface eth0
static ip_address=192.168.200.254/24

Raspberry Piを再起動させて192.168.200.254に接続できるか確認

$ sudo shutdown -r now

DHCPサーバーインストー

isc-dhcp-serverをインストール。

$ sudo apt install isc-dhcp-server

/etc/dhcp/dhcpd.confの編集

以下の2行をコメントアウト

#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

以下の行のコメントアウトを解除。

authoritative;

以下の行をファイル末尾に追加し、192.168.200.2〜192.168.200.20をリース範囲とする。 DNSサーバーはとりあえずGoogleのサーバーにしておいた(8.8.8.8, 8.8.4.4)。

subnet 192.168.200.0 netmask 255.255.255.0 {
  range 192.168.200.2 192.168.200.20;
  option routers 192.168.200.254;
  option subnet-mask 255.255.255.0;
  option broadcast-address 192.168.200.255;
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}

/etc/default/isc-dhcp-serverの編集

eth0だけに対してリースさせるために、以下の行を変更。

INTERFACES="eth0"

IP転送機能を有効にする

/etc/sysctl.conf の以下の行を変更する。これで常にIP転送機能が有効になる。

net.ipv4.ip_forward=1

NAPTの設定

有線ポート(eth0)が有効になった時にNAPTの設定を有効にする設定をする。

ifplugdのインストー

まず、ネットワークケーブルの抜き差しによってeth0のup, downの処理を させるためにifplugdをインストールする。

$ sudo apt install ifplugd

ifplugdの初期設定を行う。以下のコマンドで対話的に実行できる。

sudo dpkg-reconfigure ifplugd

結果、/etc/default/ifplugdが以下の通り設定される。

INTERFACES="eth0"
HOTPLUG_INTERFACES="eth0"
ARGS="-q -f -u0 -d10 -w -I"
SUSPEND_ACTION="stop"

/etc/network/interfacesの設定

eth0設定の部分を以下の通りにする。

iface eth0 inet manual
    pre-up /sbin/iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -j MASQUERADE
    up systemctl restart isc-dhcp-server
    post-down /sbin/iptables -t nat -D POSTROUTING -s 192.168.200.0/24 -j MASQUERADE

pre-upとpost-downでNAPTの設定、設定解除を行っている。また、upでDHCPサーバーの 再起動をしている。ネットワークケーブルを挿さずにRaspberry Piを起動した場合、 (IPアドレスが付与されていない状態ではDHCPサーバーは起動失敗するので)あとから ネットワークケーブルを挿してもDHCPサーバーとして機能しない問題があるが、上記設定で回避できる。

Raspberry Pi によるイーサネットコンバータ (1) 準備

イーサネットコンバータが必要になったので、Raspberry Piで作ってみることにした。

パソコン 有線ネットワークポート (DHCP Client)
↓
Raspberry Pi 有線ポート (DHCP Server)
↓
NAPT
↓
Raspberry Pi 無線ポート
↓
無線アクセスポイント(モバイルWi-Fiルータ)
↓
インターネット

という流れです。 普通にイーサネットコンバータを買った方が安いし速度が出そうですが、 Raspberry Piを一度使ってみたかったので…。

準備

購入したもの

家にあったもの

インストー

OSインストール(Micro SDカード作成)

GUIは不要だし、速く起動させたいので Raspbian Lite をインストールすることにした。 手順は Raspberry PiへのOSインストールの手順 ddコマンド編 そのままで OK だった。(MacOS Sierra上で実行)

OSイメージをダウンロードしてチェックし、圧縮ファイルを展開

$ curl -O http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian_lite/images/raspbian_lite-2017-07-05/2017-07-05-raspbian-jessie-lite.zip
$ curl -O http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian_lite/images/raspbian_lite-2017-07-05/2017-07-05-raspbian-jessie-lite.zip.sha256
$ shasum -a 256 2017-07-05-raspbian-jessie-lite.zip > checked.txt
$ diff checked.txt 2017-07-05-raspbian-jessie-lite.zip.sha256
$ unzip 2017-07-05-raspbian-jessie-lite.zip

MicroSDカードをMacにセットし、デバイス名を確認。

$ df -h
Filesystem      Size   Used  Avail Capacity iused      ifree %iused  Mounted on
/dev/disk0s2   223Gi  144Gi   78Gi    65% 1250450 4293716829    0%   /
devfs          191Ki  191Ki    0Bi   100%     660          0  100%   /dev
map -hosts       0Bi    0Bi    0Bi   100%       0          0  100%   /net
map auto_home    0Bi    0Bi    0Bi   100%       0          0  100%   /home
/dev/disk1s2   931Gi  825Gi  106Gi    89% 1395350 4293571929    0%   /Volumes/Macintosh HD
/dev/disk2s2   119Gi   95Gi   24Gi    81%     273 4294967006    0%   /Volumes/SSD120
/dev/disk3s1   249Mi  113Mi  136Mi    46%     512          0  100%   /Volumes/878
/dev/disk4s1   7.6Gi  2.3Gi  5.3Gi    31%       0          0  100%   /Volumes/NO NAME

→ /dev/disk4s1 だった。

MicroSDカードのパーティションをアンマウント。

$ sudo diskutil umount /dev/disk4s1
Password:
Volume NO NAME on disk4s1 unmounted

dd コマンドでイメージを書き込み。

$ sudo dd bs=1m if=2017-07-05-raspbian-jessie-lite.img of=/dev/rdisk4
dd: /dev/rdisk4: Invalid argument
1645+1 records in
1645+0 records out
1724907520 bytes transferred in 158.689131 secs (10869727 bytes/sec)

→ Invalid argument というエラーが表示されている。よくわからないが、 /dev/rdisk4 ではなく /dev/disk4 を指定して書き込んでみる。

$ sudo dd bs=1m if=2017-07-05-raspbian-jessie-lite.img of=/dev/disk4
1645+1 records in
1645+1 records out
1725629563 bytes transferred in 1028.788584 secs (1677341 bytes/sec)

書き込みがかなり遅いが、今度はエラーは出なかった。

OS起動

MicroSDカードをRaspberry Piにセットし、ネットワークケーブル(ストレート) でMacRaspberry Piを直結して起動。起動させたらMacからpingを打ってみる。 Raspbian Liteはデフォルトでavahi-daemonがインストールされているので、 raspberrypi.localで名前解決できる。

ping raspberrypi.local
PING raspberrypi.local (192.168.1.46): 56 data bytes
64 bytes from 192.168.1.46: icmp_seq=0 ttl=64 time=50.380 ms
64 bytes from 192.168.1.46: icmp_seq=1 ttl=64 time=1.706 ms
64 bytes from 192.168.1.46: icmp_seq=2 ttl=64 time=1.334 ms
^C

通信できているようだ。sshで接続してみる。

$ ssh pi@raspberrypi.local
ssh: connect to host raspberrypi.local port 22: Connection refused

接続拒否された。調べたところ、最近のRaspbianではbootパーティションsshというファイルが無いと接続拒否する設定になっているようだ。 MicroSDカードを取り出してMacに挿して

$ cd /Volumes/boot
$ touch ssh

で ‘ssh’ ファイルを作成した。再度Raspberry PiMicroSDカードをセットして 起動させ、Macからデフォルトで存在するpiユーザー(パスワード: raspberry)で 接続。

$ ssh pi@raspberrypi.local
The authenticity of host 'raspberrypi.local (2001:a452:8188:dc00:5b8a:2cff:a2c1:ce49)' can't be established.
RSA key fingerprint is SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'raspberrypi.local,2001:a452:8188:dc00:5b8a:2cff:a2c1:ce49' (RSA) to the list of known hosts.
pi@raspberrypi.local's password:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.

pi@raspberrypi:~ $

今度は接続できた。メッセージに従い、piユーザーのパスワードを変更しておく。

pi@raspberrypi:~ $ passwd
Changing password for pi.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

また、普段ログインするユーザーも作っておく。

pi@raspberrypi:~ $ sudo adduser user
Adding user `user' ...
Adding new group `user' (1001) ...
Adding new user `user' (1001) with group `user' ...
Creating home directory `/home/user' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for user
Enter the new value, or press ENTER for the default
    Full Name []: 
    Room Number []:
    Work Phone []:
    Home Phone []:
    Other []:
Is the information correct? [Y/n] Y
pi@raspberrypi:~ $ sudo adduser user sudo
Adding user `user' to group `sudo' ...
Adding user user to group sudo
Done.

無線設定

USB無線子機を接続し、確認。

$ lsusb
Bus 001 Device 004: ID 2019:ab2a PLANEX GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS]
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

→ 自動的に “PLANEX GW-USNano2 802.11n Wireless Adapter” として認識された。

Wi-Fi接続情報を作成。下記の “SSID” には接続したい無線アクセスポイントの SSIDを、"passphrase" にはパスフレーズを入力。

$ wpa_passphrase SSID passphrase

画面に表示された内容を /etc/wpa_supplicant/wpa_supplicant.conf の末尾に追加。 wlan0インターフェースを再起動。

$ sudo ifdown wlan0
$ sudo ifup wlan0
$ ifconfig
(...中略...)
wlan0     Link encap:Ethernet  HWaddr 00:22:cf:fd:8b:56
          inet addr:192.168.1.47  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: 2001:a452:8188:dc00:e417:8a7d:40ec:d4ad/64 Scope:Global
          inet6 addr: fe80::6caf:649c:143d:17b4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:9 errors:0 dropped:7 overruns:0 frame:0
          TX packets:25 errors:0 dropped:11 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:4099 (4.0 KiB)  TX bytes:6925 (6.7 KiB)

IPアドレスが取得できている。OK。基本的な設定ができたので、今日はここまで。

nkf 2.1.4 Windows

Windows 上で nkf を使って、Shift-JIS のソースを UTF-8 に変換しようと思ったが、 公式サイト ではソースコードのみの配布だった。

http://barutan.s296.xrea.com/win_bin1.html でバージョン 2.1.3 の Windowsバイナリを配布していたが、せっかくなので最新版の 2.1.4 をビルドしてみることにした。

ソースコードの中に nkf.mak という Visual Studio 2008 Express 用の Makefile があるので、これを使ってビルドすれば良い。

nmake /f nkf.mak

Visual Studio 2008 がインストールされたマシンが無かったので、Visual Studio 2015 の C コンパイラでビルドしてみたが、問題なくビルドに成功した。

Archer C7 and AirMac Express (1st Gen)

自宅用の無線LAN親機として、NECAterm WR8700N を数年間使ってきたが、 時々インターネットとの接続が切れる現象が出てきた。原因はよくわからないものの そろそろ 801.11ac 対応の親機に変えても良いかと思っていたので、買い換えることにした。 特に WR8700N に対する不満は無かったので次も NEC の機種から購入しても良かったが なんとなく別のメーカーの製品を試したくなって TP-Link 社の Archer C7 という 製品を購入することにした。

設定記録

自宅は光回線(NTT フレッツ光)を引いており、ホームゲートウェイがあるためルーター機能は不要なので

  • ホームゲートウェイとLANケーブルで接続(WANポートではなくLANポートに接続)
  • DHCPサーバー機能を無効に設定
  • IPアドレスを固定(192.168.1.250にした)...LANポート側のアドレスをDHCP(クライアント)で自動設定する機能は無いようだ

とした。また、

  • WPAグループキー更新間隔をデフォルトの0から3600(1時間)に変更(2.4GHz, 5GHz両方)
  • 2.4GHz のチャンネル幅を自動から20MHzに変更
  • UPnP を無効にした (使用する予定はない)

AirMac Express 設定

自宅では AirMac Express (初代) を使って音楽を聴いている。親機を Archer C7 に切り替えてから AirMac Express が親機に接続できなくなってしまった(通常、本体で緑のランプが点灯しているが、 オレンジ色のランプが点滅している)。調べたところ、AirMac Express 側の設定も、Archer C7 側の 設定も両方とも WPA2 に固定しなければならないことがわかった。(WPA/WPA2 という設定では 接続できない) AirMac Express (初代) は、2.4GHz (801.11b, g) しか対応していないので、2.4GHz の方のみ WPA2 に固定すれば良い。 また、Archer C7 側の設定で暗号キーを AES から自動に設定変更したが、これは接続できる/できないに 関係ないかもしれない。

親機が WR8700N の時に接続できていたのは、おそらく WR8700N では WEP と WPA2 それぞれに SSID を持っており、WEP で接続していたためと思われる。 (AirMac Express は一度初期化したので、もうわからないが)

Oracle 11g (Windows版) - 別サーバーへの複製

前の記事にも書きましたが、今回の目的は現在稼働している Oracle サーバーを仮想化し、そのまま運用を続けることです。サーバー移行の際は、いくらかの時間 Oracle を止めることはできますが、あまり長い時間止めることはできません。そのため、

という単純な方法は(時間がかかりすぎて)とることができませんでした。そこで事前に P2V してホスト名と IP アドレスを変更した仮想マシンを作っておき、サーバー移行の際は Oracle のデータだけをコピーする、という方法にトライすることにしました。具体的には

  • 移行元/移行先サーバーの Oracle を停止
  • 移行元から移行先に Oracle データをコピー
  • 移行元サーバーをシャットダウン
  • 移行先サーバーのホスト名と IP アドレスを(移行元と同じになるよう)変更
  • 移行先サーバーの Oracle を起動

というものです。

どのファイルをコピーするべきか

ユーザー管理データベース・バックアップの作成 を参考に考えてみることにします。

「データベース全体のユーザー管理バックアップの作成」のところを見ると、

オペレーティング・システム・ユーティリティを使用して、すべてのデータファイルと、初期化パラメータ・ファイルのCONTROL_FILESパラメータで指定された すべての制御ファイルのバックアップを作成します。また、初期化パラメータ・ファイルおよびその他のOracle製品の初期化ファイルもバックアップします。

とあります。今回、パラメータファイルは移行元/先で同一のはずなので、

  • データファイル
  • 制御ファイル

をコピーすれば良いことになります。しかし、このマニュアルの説明は障害発生時のリカバリを想定しているのでオンラインREDOログ、アーカイブREDOログの事に触れていませんが、今回の場合は移行先の方が古いオンラインREDOログ、アーカイブREDOログの状態であるためこれらもコピーするべきなのではないかと思います。結局、

  • データファイル
  • 制御ファイル
  • オンラインREDOログ
  • アーカイブREDOログ

をコピーすれば良いと思われます。

各ファイルのパスの調べ方

インスタンスごとに下記SQL文で調べられる。

データファイル
select tablespace_name, file_name from dba_data_files

tablespace_name は表領域名。

制御ファイル
select name from v$controlfile
オンラインREDOログ
select group#, member from v$logfile

group# はメンバーが含まれるロググループの番号。

アーカイブREDOログ

これは少しややこしいところがあります。 Recovery Manager環境の構成 をよく読む必要がある(と思います)。 まず、フラッシュリカバリ領域が有効になっているかどうかで話が変わってきます。有効である場合は、

select name from v$recovery_file_dest;

で確認できるフラッシュリカバリ領域にファイルが作成されます。例えば、上記 SQL

C:\oracle\flash_recovery_area

と表示された場合は、そのフォルダの下に、sid\ARCHIVELOG というフォルダが作成され、その中の日付がついたフォルダ内にアーカイブREDOログはできます。 ファイル名は何らかのルールで決まっているようですが、よくわかりません(初期化パラメータ LOG_ARCHIVE_FORMAT は無視されます)。 この他に、初期化パラメータ LOG_ARCHIVE_DEST_n (n=1〜31)で指定されるフォルダにもアーカイブREDOログはできます。

フラッシュリカバリ領域が無効である場合は、初期化パラメータ LOG_ARCHIVE_DEST_n, LOG_ARCHIVE_DUPLEX, LOG_ARCHIVE_DUPLEX_DEST で指定されるフォルダに アーカイブREDOログは作成されます。(LOG_ARCHIVE_DUPLEX, LOG_ARCHIVE_DUPLEX_DEST は非推奨のオプション。フラッシュリカバリ領域が有効である場合は この2パラメータを指定するとインスタンスを起動できなくなるとのことです)

と、ここまで書いた所でもう少し簡単に調べる方法を見つけました。

archive log list

というコマンドの出力結果に「アーカイブ先」として表示されます。ただし、アーカイブ先が USE_DB_RECOVERY_FILE_DEST となっている場合は上記のフラッシュリカバリ領域がアーカイブ先になります。

Oracle 11g (Windows版) - 起動と停止

仕事で Oracle 11g が乗っかったある Windows サーバーを仮想化することになった。が、Oracle サーバーの管理方法は全く知らない。基本的なところから勉強してみることにした。

Windows サービスによる Oracle インスタンスの起動と停止

参考: Windowsでのデータベースの管理

Windows の場合、Oracle インスタンスと1対1に対応した Windows サービスが OS 起動時に自動起動するようになっている。さらに、デフォルト(レジストリ ORAsidAUTOSTART が TRUE)の場合はサービスの起動によってインスタンスの起動、すなわち SQL*Plus での

startup

が自動的に行われる。なお、ORAsidAUTOSTART の sidOracle System Identifier であり、インスタンスの識別子である。つまり、1つのマシン上で複数インスタンスが起動している場合(実は、今回メンテしようとしているサーバーには複数インスタンスが乗っかっている!)、それらを区別するためのものである。

また、サービスを停止させると、デフォルトの設定では SQL*Plus で

shutdown immediate

を実行したのと同様の形でインスタンスも終了する。これらの動作にはレジストリ ORAsidSHUTDOWN および ORAsidSHUTDOWNTYPE が関係している。 結局、デフォルトの設定では OS(Windows) 起動時に Oracle インスタンスの起動が行われ、OS シャットダウン時には(進行中のトランザクションロールバックされてから)Oracle インスタンスは停止するということである。

SQL*Plus の起動

参考: Windows環境におけるデータベース・ユーザーの認証

コマンドプロンプトを起動して、

sqlplus /nolog

で(データベースに接続しない状態で) SQL*Plus を起動する。Windows 版の Oracle の場合、(Windows の)ログインユーザーが ora_dba グループに所属している場合、以下のコマンドによりパスワード無しで SYSDBA 権限でローカルマシンで動いている Oracle データベースに接続できる。

connect / as sysdba

SQL*Plus による Oracle インスタンスの停止

上記の通り、Windows では何もしなくても Oracle インスタンスが起動された状態になっているので、よく本に載っている SQL*Plus での起動を試してみるためには、一度接続していったん停止させてから起動を試みる必要がある。なので、まず停止方法から。

shutdown [normal | transactional | immediate | abort]

normal は新たな接続を禁止し、既にある接続が終了するまで待ってからシャットダウンする。接続を張りっぱなしにするアプリケーションもあったりするのでこのモードでのシャットダウンは実際には使用することは無さそう。abort は強制的なシャットダウンであり、整合性が取れていない状態になってしまう(次回の起動時にリカバリ処理が走る)ので推奨されていない。よって通常は transactional か immediate を使用することになると思う。transactional は、進行中のトランザクションの完了を待ってからシャットダウンする。immediate は進行中のトランザクションロールバックさせてからシャットダウンする。いずれもシャットダウン後は整合性が取れた状態になる。

SQL*Plus による Oracle インスタンスの起動

起動は停止と異なり、段階がある。状態は

  • 停止 (S)
  • NOMOUNT 状態 (N)
  • MOUNT 状態 (M)
  • OPEN 状態 (O)

の4つある。状態を移動させるコマンドは

移動方向 コマンド
S→O startup
S→M startup mount
S→N startup nomount
N→M alter database mount;
M→O alter database open;

である。OPEN 状態になって初めて一般のクライアントアプリケーションがデータベースにアクセスできるようになる。NOMOUNT や MOUNT 状態はメンテナンスの時に使用する(どんな時に使うのかはまだよくわかっていないが)。

Oracle 関係の Windows サービス

Windows 版の Oracle にはいくつかの Windows サービスが登録されている。

サービス名 スタートアップの種類 説明
Oracle sid VSS Writer Service 手動 (まだわかっていない)Volume Shadow Copy を使ったバックアップに必要?
OracleDBConsolesid 自動 Enterprise Manager を使用するために必要なサービス
OracleJobSchedulersid 無効 (まだわかっていない)
OracleMTSRecoveryService 自動 (まだわかっていない)
OracleorahomeTNSListener 自動 リスナー
OracleServicesid 自動 (最初に説明した)Oracleインスタンスと1対1に対応したサービス

ここで、sid の部分には SID が入り、orahome の部分には Oracle ホーム名が入る。Oracle ホーム名は Oracle インストール時に設定した名前である。スタートメニューに "Oracle - OraDb11g_home1" のように表示されていたら Oracle ホーム名は "OraDb11g_home1" である。

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 を呼び出せるのですが、さすがにこれだけでは使いづらいので、 便利に使うためのクラスライブラリを準備していきたいと思います。