【问题标题】:Fortran fixed-size multidimensional arrays in interoperable derived types可互操作派生类型中的 Fortran 固定大小多维数组
【发布时间】:2018-05-15 15:32:18
【问题描述】:

我有一个 Fortran 库,我正在尝试为其创建 C 绑定。 Fortran 库使用派生类型中包含的固定大小的多维数组。 (这些最初是旧 Fortran 代码中的全局变量;出于封装的目的,我将所有全局变量放入派生类型中。)如果我使用这个库在 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

当我运行它时,我在 set_structs 中遇到了 i = 1, j = 103 的段错误。但是,如果我注释掉对 iarray 的所有引用,它就可以正常工作。所以这个问题似乎只有在 Fortran 派生类型中有 1 个以上的多维数组时才会出现。单个多维数组可以正常工作(带有 iarray 注释的 struct_a),多个一维数组可以正常工作(struct_b)。我还测试了根本没有派生类型,只是将四个数组从 C (两个二维和 2 个一维)传递给 Fortran,这也很好。我有点不知所措了,所以我非常感谢一些关于如何正确执行此操作的建议。

编辑:正如 francescalus 在下面的评论中所指出的,这个例子的问题只是我试图访问 iarray 的越界元素,所以它不是我的代码真正问题的一个很好的例子.有关实际原因和解决方案,请参阅已接受的答案。

【问题讨论】:

  • 你不只是访问越界的元素吗?您的j 最高可达RSIZE2,但iarray 组件的第二维范围为ISIZE2
  • 啊,愚蠢的我。你完全正确。我浪费了几个小时来创建这个“最小的工作示例”。不幸的是,这种错误不是我实际代码中的问题,所以现在我必须弄清楚那里发生了什么。无论如何,感谢您发现我的错误,我现在将关闭它。

标签: arrays multidimensional-array fortran interop


【解决方案1】:

我在我的真实代码中发现了问题,以防有人想知道。似乎与头文件中的#defines 有关。例如,我有如下陈述:

#define IQX 360
#define IWX IQX/8+2
#define IZX IQX+IWX

显然这不起作用,如果我更熟悉 C 预处理器,我可能会知道这一点。而是这样做:

#define IQX 360
#define IWX 47
#define IZX 407

【讨论】:

  • 您可能已经edited 您之前的答案,这实际上不是一个实际的答案。这不是一个讨论线程。请在tour查看如何使用本网站。
猜你喜欢
  • 1970-01-01
  • 2014-04-16
  • 2014-10-18
  • 1970-01-01
  • 2017-08-12
  • 2013-08-13
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多