2015-03-24 108 views
1

作为此post的扩展,我有派生类型,它们本身具有成员派生类型。实施例下面:包含派生类型的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。解决方案可以看到here。但是,这里不仅仅是一个派生类型,它是派生类型,其成员是派生类型本身。我是否需要为COMPLEXF创建Y的每个成员的子例程,即SETY_A,QUERYY_A,SETY_B,QUERYY_BSIZE,SQUERYY_B等?或者有更好的方法来解决这个问题吗?

回答

2

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

至于提出的y成分的存在是一个细节的C代码可能并不需要关心 - 而不是调用sety_a你可以只将其命名为set_a的过程。

如果要对COMPLEXF类型的组件进行很多操作,并且您希望避免间接级别,或者同一类型的许多此类组件为COMPLEXF,则可以使用C地址与该组件对应的子对象作为不透明手柄。

例如起见,改变在linked answerGetHandleReleaseHandle程序与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子对象的工作 - 使用完全相同的查询* /套*程序作为链接答案。

有没有必要写一个程序,取消分配在这种情况下,y_handle提名的对象,因为与y组件相关的子对象的生命周期由一生的对象,它有子对象确定 - 即子对象会当调用COMPLEXF超级对象的ReleaseHandle时,请离开。

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

+0

感谢您的详细解答。因此,在Fortran中,我仍然可以更改COMPLEXF变量的y SIMPLEF组件,然后C将使用C_LOC安排返回更新的组件。我猜如果我想要的话,我仍然可以在这个阶段访问C端的y子组件,或者我可以将y(已经用C_LOC获得)与另一个SIMPLEF类型的变量相等,并且C中的值更新。 – Stam 2015-03-25 08:52:13