29.2 Big arrays in the Caml-C interface

29.2.1. Include file
29.2.2. Accessing a Caml bigarray from C or Fortran
29.2.3. Wrapping a C or Fortran array as a Caml big array

C や Fortran のコードと Caml のコードを結びつける( 18 章「C と Objective Caml のインタフェースで述べられています) C のスタブコードは、次のようにして big array を利用することができます。

29.2.1 Include file

C スタブファイルには必ず <caml/bigarray.h> をインクルードしなくてはいけ ません。これは、以下で述べる関数と定数とマクロを宣言します。

29.2.2 Accessing a Caml bigarray from C or Fortran

もし v が big array を表す Caml の値だとすると、Data_bigarray_val(v) と いう式は配列のデータ部分へのポインタを返します。このポインタは void 型 で、適切な C の型にキャストすることができます。(例えば double [], char [][10], などなど)

Caml の big array の様々な情報は、C で次のように得ることができます。

C の式返る値
Bigarray_val(v)->num_dims次元の数
Bigarray_val(v)->dim[i]i番目の次元
Bigarray_val(v)->flags & BIGARRAY_KIND_MASK配列の要素の種類

配列の要素の種類は、次の定数のうちのどれかです。

定数要素の種類
BIGARRAY_FLOAT3232ビットの単精度浮動小数点数
BIGARRAY_FLOAT6464ビットの倍精度浮動小数点数
BIGARRAY_SINT88ビット符号付き整数
BIGARRAY_UINT88ビット符号なし整数
BIGARRAY_SINT1616ビット符号付き整数
BIGARRAY_UINT1616ビット符号なし整数
BIGARRAY_INT3232ビット符号付き整数
BIGARRAY_INT6464ビット符号付き整数
BIGARRAY_CAML_INT31ビットか63ビットの符号付き整数
BIGARRAY_NATIVE_INT32ビットか64ビットの(プラットフォームネイティブな)整数

以下は、2次元の big array を C と Fortran の関数に渡す例です。

extern void my_c_function(double * data, int dimx, int dimy);
extern void my_fortran_function_(double * data, int * dimx, int * dimy);

value caml_stub(value bigarray)
{
  int dimx = Bigarray_val(bigarray)->dim[0];
  int dimy = Bigarray_val(bigarray)->dim[1];
  /* C passes scalar parameters by value */
  my_c_function(Data_bigarray_val(bigarray), dimx, dimy);
  /* Fortran passes all parameters by reference */
  my_fortran_function_(Data_bigarray_val(bigarray), &dimx, &dimy);
  return Val_unit;
}

29.2.3 Wrapping a C or Fortran array as a Caml big array

既にメモリ領域が割り当てられた C や Fortran の配列へのポインタ p は、 alloc_bigarray や alloc_bigarray_dims 関数を使って Caml の世界に持って 帰ることができます。

alloc_bigarray(kind | layout, numdims,p, dims)

p で示されるデータをラップして Caml の big array として返します。 kind は配列の要素の種類です(上で述べた BIGARRAY_ のうちのひとつ)。 layout には、C の配列なのか(BIGARRAY_C_LAYOUT)、Fortran の配列なのか (BIGARRAY_FORTRAN_LAYOUT)を指定します。numdims は配列の次元の数です。 dmis は numdims の長さの整数の配列で、それぞれの配列のサイズを表します。

alloc_bigarray_dims(kind | layout, numdims, p, (long) dim1, (long) dim2, …, (long) dimnumdims)

> alloc_bigarray と同じですが、それぞれの次元の配列のサイズを配列として 渡すのではなく、関数呼び出しの引数に直接追加されています。

以下は、静的に割り当てられた C と Fortran の配列をどうやって Caml から扱えるようにするかを表した例です。

extern long my_c_array[100][200];
extern float my_fortran_array_[300][400];

value caml_get_c_array(value unit)
{
  long dims[2];
  dims[0] = 100; dims[1] = 200;
  return alloc_bigarray(BIGARRAY_NATIVE_INT | BIGARRAY_C_LAYOUT,
                        2, my_c_array, dims);
}

value caml_get_fortran_array(value unit)
{
  return alloc_bigarray_dims(BIGARRAY_FLOAT32 | BIGARRAY_FORTRAN_LAYOUT,
                             2, my_fortran_array_, 300L, 400L);
}