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

作为这篇文章的扩展,我已经派生出了具有成员派生类型的类型。 示例如下:

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。 解决方案可以在这里看到。 然而,这里它不仅仅是一个派生类型,它是一个派生类型,其成员本身就是派生类型。 我是否需要为每个Y成员创建COMPLEXF子程序,即SETY_A,QUERYY_A,SETY_B,QUERYY_BSIZE,SQUERYY_B等? 或者有更好的方法来解决这个问题吗?

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

如上所述, y组件的存在是C代码可能不需要关心的细节 – 而不是调用过程sety_a您可以将其命名为set_a

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

例如,更改链接答案中的GetHandleReleaseHandle过程以使用COMPLEXF类型作为顶级类型(即 – 在该答案中替换所有SIMPLEF外观的COMPLEXF )。 然后你可以编写一个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组件关联的子对象的生命周期由具有该子对象的对象的生命周期决定 – 当ReleaseHandle时该子对象将消失调用COMPLEXF超级对象。

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