我有一个C代码(我不是上述代码的所有者),它生成了以下 struct :

struct Vector
{
  int size;
  double data[3];
};

struct VerticesVect
{
  int size;
  struct Vector* data;
};

And so on:有许多额外的 struct (通常是先前定义的 struct ).

我需要调用所述C代码/库从一个Fortran代码.Fortran代码将使用以前C生成的 struct .Fortran代码不会以任何方式编写/编辑它们,它只需要它们作为输入.

我试图找到一种方法来声明这些类型在Fortran中,以便我可以使用它们.

use, intrinsic :: ISO_C_BINDING

其次是

type, bind(c) :: Vector
          integer(kind=C_INT32_T) :: size
          real(kind=C_DOUBLE) :: data(3)
      end type Vector

显然没问题

  type, bind(c) :: VerticesVect
      integer(kind=c_int) :: size
      type(Vector), dimension(:) :: data
  end type VerticesVect

但无效("数据必须具有明确的形状"),也

  type, bind(c) :: VerticesVect
      integer(kind=c_int) :: size
      type(Vector), pointer :: data
  end type VerticesVect

("组件'data'不能具有POINTER属性,因为它是BIND(C)派生类型'vertesvect'的成员")

我所能想到的可分配、指针、定位(:)的任何组合似乎也不有效.

不幸的是,指定一个静态尺寸,使其足够大以涵盖所有情况不是一个可接受的解决方案,因为所有后续构造的"复合"最大尺寸最终导致一个不合理的大的总对象.

有没有一种方法可以编写这些声明,使编译器接受它,并且所有内容都正确地映射?我可以/应该使用c_ptr类型吗?我可以/应该摆脱bind(c)吗?

谢谢你的帮助

推荐答案

这个...

      type(Vector), dimension(:) :: data

...试图将成员data声明为假定形状的array. 这在C意义上是错误的,C指针不是array. 在C绑定意义上,明确禁止可互操作的定义类型拥有假定大小或假定形状数组的成员,这也是错误的.

这个...

      type(Vector), pointer :: data

...它似乎更符合逻辑,但也不正确,因为Fortran指针和C指针虽然在概念上相似,但并不完全相似. C绑定将C指针映射到类型type(c_ptr). 这里有一些警告,但我们不需要在这里挖掘这些.

因此,定义与具有指针成员的C struct 相对应的可互操作的用户定义类型的方法是在Fortran端and上对相应成员使用type(c_ptr)来赋予该类型bind(c)属性:

  type, bind(c) :: VerticesVect
      integer(kind=c_int) :: size
      type(c_ptr) :: data
  end type VerticesVect

此外,您将希望能够从Fortran端access个对象. 因此,您可能需要使用ISO_C_BINDINGc_f_pointer()功能. 这是C指针和Fortran指针之间的主要互操作桥梁.例如:

    type(VerticesVect) :: vertices

    ! ... assign an appropriate value to 'vertices' ...

    type(Vector), dimension(:), pointer :: vectors
    c_f_pointer(vertices%data, vectors, (/vertices%size/))

    ! ... use 'vectors' to access the data ...

虽然您说您只需要读访问,但读和写访问都应该工作正常.

C++相关问答推荐

生成C代码时自动复制/生成' tmwtypes.h '依赖项

使用额外的公共参数自定义printf

将指针作为参数传递给函数

将 struct 变量赋给自身(通过指针取消引用)是否定义了行为?

为什么net/if.h在ifaddrs.h之前?

当我更改编译优化时,相同的C代码以不同的方式运行

fwrite无法写入满(非常大)缓冲区

CC2538裸机项目编译但不起作用

S将C语言宏定义为自身的目的是什么?(在glibc标题中看到)

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

在创建动态泛型数组时,通过realloc对故障进行分段

为什么realloc函数在此代码中修改变量?

如何在zOS上编译共享C库

Linux/C:带有子进程的进程在添加waitid后都挂起

解密Chrome加密密钥

在我的函数中实现va_arg的问题

分支预测和UB(未定义的行为)

If语句默认为true

C 语言中霍尔分区的快速排序算法

在 C/C++ 中原子按位与字节的最佳方法?