У меня есть библиотека Фортрана, для которой я пытаюсь создать привязки Си.Библиотека Фортрана использует многомерные массивы фиксированного размера, содержащиеся в производных типах.(Изначально это были глобальные переменные в унаследованном коде Fortran; я помещаю все глобальные переменные в производные типы для инкапсуляции.) Если я создаю тестовый пример в Fortran с использованием этой библиотеки, в этом случае производные типы инициализируютсяв коде Фортрана все идет хорошо, но когда я пытаюсь сделать то же самое в C, и в этом случае производные типы инициализируются в C как структуры, я получаю ошибку сегментации.
Вот минимальный пример, который показываетпроблема.Библиотека Fortran также использует производный тип группировки, содержащий другие производные типы, поэтому я включил это в пример.
testmod.f90:
module testmod
use iso_c_binding
implicit none
integer(c_int), parameter :: RSIZE1 = 360
integer(c_int), parameter :: RSIZE2 = RSIZE1/2
integer(c_int), parameter :: ISIZE1 = RSIZE1
integer(c_int), parameter :: ISIZE2 = ISIZE1/4
type, bind(c) :: struct_a
real(c_double) :: rarray(RSIZE1,RSIZE2)
integer(c_int) :: iarray(ISIZE1,ISIZE2)
end type struct_a
type, bind(c) :: struct_b
real(c_double) :: rvec(RSIZE1)
integer(c_int) :: ivec(ISIZE1)
end type struct_b
type, bind(c) :: struct_group
type(struct_a) :: a
type(struct_b) :: b
end type struct_group
contains
subroutine set_structs(group) bind(c, name="set_structs")
type(struct_group), intent(inout) :: group
integer i, j
do i = 1, RSIZE1
group%b%rvec(i) = dble(i)
group%b%ivec(i) = i
do j = 1, RSIZE2
group%a%rarray(i,j) = dble(i*j)
group%a%iarray(i,j) = i*j
write(*,*) "Here", i, j
end do
end do
end subroutine set_structs
end module testmod
test.h:
#pragma once
#define RSIZE1 360
#define RSIZE2 RSIZE1/2
#define ISIZE1 RSIZE1
#define ISIZE2 ISIZE1/4
typedef struct
{
double rarray[RSIZE1*RSIZE2];
int iarray[ISIZE1*ISIZE2];
} struct_a;
typedef struct
{
double rvec[RSIZE1];
int ivec[ISIZE1];
} struct_b;
typedef struct
{
struct_a a;
struct_b b;
} struct_group;
extern void set_structs(struct_group *group);
test.c:
#include "test.h"
int main()
{
struct_group group;
set_structs(&group);
return 0;
}
Компилировать следующим образом:
gfortran -c -fPIC -Wall testmod.f90
gcc -c -fPIC -Wall test.c
gfortran -o test testmod.o test.o
Когда я запускаю это, я получаю segfault в set_structs для i = 1, j =103. Однако, если я закомментирую все ссылки на iarray, он будет работать нормально.Таким образом, проблема возникает только в том случае, если в производном типе Фортрана имеется более 1 многомерного массива.Один многомерный массив работает нормально (struct_a с закомментированным iarray), а несколько одномерных массивов работают нормально (struct_b).Я также тестировал без производных типов, просто передавая четыре массива в Fortran из C (два 2-мерных и 2 1-мерных), и это тоже отлично работает.Я как бы в своем уме, поэтому я очень ценю несколько советов о том, как сделать это правильно.
РЕДАКТИРОВАТЬ: как отмечено francescalus в комментарии ниже, проблема с этим примером просточто я пытаюсь получить доступ к элементам iarray, выходящим за границы, так что это не хороший пример реальной проблемы с моим кодом.См. Принятый ответ для фактической причины и решения.