Fortran派生类型包含可从C访问的派生类型

时间:2015-03-24 22:09:39

标签: c pointers fortran fortran-iso-c-binding derived-types

作为此post的扩展,我已经派生了具有成员派生类型的类型。示例如下:

module simple
use  iso_c_binding

TYPE SIMPLEF
  INTEGER :: A
  INTEGER, POINTER :: B, C(:)
END TYPE SIMPLEF

TYPE COMPLEXF
  INTEGER :: X
  TYPE (SIMPLEF) :: Y
END TYPE COMPLEXF
end module simple

如上文所述,目标是在C中具有类似的派生类型,并且能够将值来回传递给Fortran。可以看到解决方案here。然而,这里它不仅仅是一个派生类型,它是一个派生类型,其成员本身就是派生类型。我是否需要为每个Y成员创建COMPLEXF子程序,即SETY_A,QUERYY_A,SETY_B,QUERYY_BSIZE,SQUERYY_B等?或者有更好的方法来解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

可以使用相同的方法。什么是最好的取决于您认为C客户端与Fortran对象交互的最佳方式。在编写太多代码之前,应该考虑一下这个问题。

如上所述,y组件的存在是C代码可能不需要关心的细节 - 而不是调用程序sety_a,您只需将它命名为set_a {1}}。

如果COMPLEXF类型的组件上有许多操作,并且您希望避免间接级别,或者有许多相同类型的COMPLEXF组件,那么你可以使用与该组件对应的子对象的C地址作为不透明句柄。

为了示例,更改linked answer中的GetHandleReleaseHandle过程以使用COMPLEXF类型作为顶级类型(即 - 替换COMPLEXF表示该答案中SIMPLEF的所有外观。然后,您可以按照以下方式编写QueryYHandle程序或类似程序。

FUNCTION QueryYHandle(handle) RESULT(y_handle)
  TYPE(C_PTR), INTENT(IN), VALUE :: handle
  TYPE(C_PTR) :: y_handle
  TYPE(COMPLEXF), POINTER :: p
  !***
  CALL C_F_POINTER(handle, p)
  y_handle = C_LOC(p%y)
END FUNCTION QueryYHandle

现在,您可以直接使用SIMPLEF子对象的句柄 - 使用与链接答案中完全相同的Query * / Set *过程。

在这种情况下,没有必要编写一个过程来释放由y_handle指定的对象,因为与y组件关联的子对象的生命周期由生命周期决定具有该子对象的对象 - 当调用COMPLEXF超级对象的ReleaseHandle时,该子对象将消失。

请注意,如上所述,在语言之间传递错误的句柄类型的方法中没有任何保护措施(例如 - 如果C代码意外地调用了旨在与COMPLEXF一起使用的过程处理实际上是SIMPLEF对象的句柄。如果这有问题,那么可以添加保护,可能是通过将句柄类型与用作不透明句柄的对象中的C地址捆绑在一起,并在尝试将Fortran指针与C地址指定的对象关联之前检查该句柄类型。