OCaml でバイナリデータの読み書き Bigarray 編 [OCaml]
以前 OCaml でのバイナリデータの読み書きの上手い方法が分からないという話 [1] を書いた。
この間 ocaml_beginners の話題で知ったのだが Bigarray というモジュールの map_file 関数を使うと C の整数配列をメモリに展開してくれるらしい。
C の構造体をそのままダンプしたようなファイルも結局のところアラインメントの関係で32ビットアーキテクチャなら32ビットずつの並びになっているのが普通なのだからこれを使うともうちょっと綺麗に書けるのではないかと思った。
まずはこういう C 構造体を想定する。
#include <stdio.h>
#include <stdlib.h>
typedef struct something_tag {
char signiture[8];
int some_data1;
char some_flag;
unsigned int some_data2;
} something;
int main(int argc, char* argv[])
{
FILE* fh;
something buf = {"SOMETHNG", 777, 'A', 4294967295};
if (argc < 2) return 1;
fh = fopen(argv[1], "w");
fwrite(&buf, sizeof(buf), 1, fh);
fclose(fh);
}
OCaml の map_file 関数で配列にマップしてこのメンバを取り出す。
open Bigarray
let _ =
let fd = Unix.openfile Sys.argv.(1) [Unix.O_RDONLY] 0644 in
let dat = Array1.map_file fd int32 c_layout false (-1) in
let some_data1 = Array1.get dat 2 in
let some_flag = Array1.get dat 3 in
let some_data2 = Array1.get dat 4 in
print_endline (Int32.to_string some_data1);
print_char (char_of_int (Int32.to_int (Int32.logand some_flag 0xffl)));
print_endline "";
print_endline (Int64.to_string (Int64.neg (Int64.add (Int64.logxor (Int64.of_int32 some_data2) 0xffffffffL) 1L)));
…。やっぱりいまいちでした。符号無し32ビット整数が欲しい。
あとこの map_file 関数ではエンディアンはどういう扱いを受けるんだろうか?
[1] http://blog.so-net.ne.jp/rainyday/2006-07-09
コメント 0