作为此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等?或者有更好的方法来解决这个问题吗?
答案 0 :(得分:2)
可以使用相同的方法。什么是最好的取决于您认为C客户端与Fortran对象交互的最佳方式。在编写太多代码之前,应该考虑一下这个问题。
如上所述,y
组件的存在是C代码可能不需要关心的细节 - 而不是调用程序sety_a
,您只需将它命名为set_a
{1}}。
如果COMPLEXF
类型的组件上有许多操作,并且您希望避免间接级别,或者有许多相同类型的COMPLEXF
组件,那么你可以使用与该组件对应的子对象的C地址作为不透明句柄。
为了示例,更改linked answer中的GetHandle
和ReleaseHandle
过程以使用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地址指定的对象关联之前检查该句柄类型。