例: 割り振り可能引数およびポインター引数
この例は、以下のマトリックスを乗算するために、相互運用可能プロシージャーで割り振り可能配列引数および配列ポインター引数を使用する方法を示しています。
1 つのプロシージャーが Fortran 側で定義され、C 側から呼び出されます。
| 3, 5| |1 0|
| 6, 7| X | |
|-1, 2| |2 1|
Fortran 側で、マトリックスを乗算する matrix_mult_fortran プロシージャーは以下のように定義されます。
SOUBROUTINE matrix_mult_fortran(res, a, b) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
REAL(C_DOUBLE), ALLOCATABLE, INTENT(OUT) :: res(:,:) !Allocatable array
REAL(C_DOUBLE), POINTER, INTENT(IN) :: a(:,:) !Array pointer
REAL(C_DOUBLE), POINTER, INTENT(IN) :: b(:,:) !Array pointer
INTEGER(8) :: ub1, ub2
ub1 = UBOUND(a,1) - LBOUND(a,1)+1
ub2 = UBOUND(b,2) - LBOUND(b,2)+1
ALLOCATE(res(ub1, ub2))
res = MATMUL(a, b)
END
C 側で、Fortran 側で定義されている matrix_mult_fortran プロシージャーが最初に宣言され、main 関数で呼び出されます。
#include <stdio.h>
#include <assert.h>
#include "ISO_Fortran_binding.h"
// Prototype for the function that is defined on the Fortran side.
void matrix_mult_fortran(CFI_cdesc_t * res, CFI_cdesc_t * a, CFI_cdesc_t * b);
// Function to print a Fortran array described by a CFI descriptor
void print2DFortranArrayOfDoubles(CFI_cdesc_t * d);
int main()
{
CFI_CDESC_T(2) a, b, res;
CFI_cdesc_t * desc_a = (CFI_cdesc_t *) &a;
CFI_cdesc_t * desc_b = (CFI_cdesc_t *) &b;
CFI_cdesc_t * desc_res = (CFI_cdesc_t *) &res;
// Because Fortran is column major and C is row major, the input matrixes
// defined on the C side are transposed.
double matrixa[2][3] = { {3, 6, -1}, {5, 7, 2} };
double matrixb[2][2] = { {1, 2}, {0, 1} };
const CFI_index_t a_extents[2] = { 3, 2 };
const CFI_index_t b_extents[2] = { 2, 2 };
int rc;
rc = CFI_establish(desc_a,
matrixa,
CFI_attribute_pointer,
CFI_type_double,
sizeof(double),
(CFI_rank_t)2,
a_extents);
// Make sure that the result is successful.
assert(CFI_SUCCESS == rc);
rc = CFI_establish(desc_b,
matrixb,
CFI_attribute_pointer,
CFI_type_double,
sizeof(double),
(CFI_rank_t)2,
b_extents);
assert(CFI_SUCCESS == rc);
rc = CFI_establish(desc_res,
NULL,
CFI_attribute_allocatable,
CFI_type_double,
sizeof(double),
(CFI_rank_t)2,
NULL);
assert(CFI_SUCCESS == rc);
// Call the Fortran procedure to multiply the matrix.
matrix_mult_fortran(desc_res, desc_a, desc_b);
assert(desc_res->base_addr);
// Call the C function to print the result.
print2DFortranArrayOfDoubles(desc_res);
rc = CFI_deallocate(desc_res);
assert(CFI_SUCCESS == rc);
return 0;
}
マトリックスの表示を調整する print2DFortranArrayOfDoubles 関数も、C 側で定義されます。
void print2DFortranArrayOfDoubles(CFI_cdesc_t * d)
{
CFI_index_t extents[2];
CFI_index_t strides[2];
int i, j;
char * prow;
prow = (char *)d -> base_addr;
extents[0] = d->dim[0].extent;
extents[1] = d->dim[1].extent;
strides[0] = d->dim[0].sm;
strides[1] = d->dim[1].sm;
// Print the values of the array one row at a time.
// Note: This is not cache friendly, because Fortran arrays are column major.
for(i = 0; i < extents[0]; i++)
{
char * tp = prow;
for(j = 0; j < extents[1]; j++)
{
printf("%f ", *(double *)tp);
tp += strides[1];
}
prow += strides[0];
printf(":¥n");
}
}
出力は次のようになります。13.0 5.0
20.0 7.0
3.0 2.0