Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
字符串的C和Fortran互操作性_C_Arrays_Fortran_Fortran Iso C Binding - Fatal编程技术网

字符串的C和Fortran互操作性

字符串的C和Fortran互操作性,c,arrays,fortran,fortran-iso-c-binding,C,Arrays,Fortran,Fortran Iso C Binding,我试图从C中调用一些Fortran代码,但没有找到传递C字符数组的正确方法 SUBROUTINE My_F_Code (c_message) BIND(C, NAME='my_f_code') USE ISO_C_BINDING IMPLICIT NONE CHARACTER*(C_CHAR) c_message CHARACTER*(256) f_message CALL C_F_POINTER( C_LOC(

我试图从C中调用一些Fortran代码,但没有找到传递C字符数组的正确方法

   SUBROUTINE My_F_Code (c_message)  BIND(C, NAME='my_f_code')
     USE ISO_C_BINDING
     IMPLICIT NONE
     CHARACTER*(C_CHAR)      c_message
     CHARACTER*(256)         f_message
     CALL C_F_POINTER( C_LOC(c_message), f_message)
     WRITE(*,*) f_message,LEN(f_message)
   END
BIND(C)
强制参数C_消息的大小为1。如何访问c_消息字符串的其他元素

编译器:GCC4.8.2

我试图从C中调用一些Fortran77代码,但没有找到传递C字符数组的正确方法

   SUBROUTINE My_F_Code (c_message)  BIND(C, NAME='my_f_code')
     USE ISO_C_BINDING
     IMPLICIT NONE
     CHARACTER*(C_CHAR)      c_message
     CHARACTER*(256)         f_message
     CALL C_F_POINTER( C_LOC(c_message), f_message)
     WRITE(*,*) f_message,LEN(f_message)
   END
我使用过的所有Fortran 77实现都为与C的互操作提供了特定于实现的机制。通常,这些机制涉及C端了解Fortran编译器使用的名称混乱和参数传递约定,并在接口处使用它们。GCC系统的约定并不难使用

不过,您似乎对Fortran 2003中引入的Fortran/C互操作功能感兴趣。假设您的Fortran 77代码也符合Fortran 2003(或者可以这样做),那么应该可以在Fortran 2003中编写一个可互操作的包装器。但是,请注意,C interop功能不能(直接)提供Fortran变量或长度大于1或与C_char不同类型的
character
类型的子程序参数的互操作性。另一方面,请记住Fortran字符对象的长度与字符数组的维数不同

您有两个可互操作的备选方案来提供面向C的接口,通过该接口可以接受C
char
数组。也许最清楚的方法是接受Fortran假定的大小
字符
数组:

SUBROUTINE My_F_Code (c_message)  BIND(C, NAME='my_f_code')
    USE ISO_C_BINDING
    IMPLICIT NONE
    CHARACTER(kind=C_CHAR), dimension(*), intent(in) :: c_message
    ! ...
END
最可能的替代方法是直接接受C的数组指针:

SUBROUTINE My_F_Code (c_message)  BIND(C, NAME='my_f_code')
    USE ISO_C_BINDING
    IMPLICIT NONE
    type(C_PTR), value :: c_message
    ! ...
END
如果C端数组指针可能为空,则必须使用后者。如果不能依赖数组以null结尾,则两者都需要传递显式长度

在任何情况下,如果您最终想要一个长度大于1的Fortran
字符
变量(与维数大于1的数组相反),那么可互操作接口不能直接提供这一点——此类类型不属于C互操作规定适用的类型。除非您可以依赖默认字符种类为
c_char
,否则您需要将它们与copy-in(/copy-out)耦合,以便在种类之间转换字符。使用前一个接口,很明显可以将数组复制到长度大于1的Fortran标量
字符
。对于指针变量,可以使用如下转换函数:

subroutine C_string_ptr_to_F_string(C_string, F_string)
    use ISO_C_BINDING
    type(C_PTR), intent(in) :: C_string
    character(len=*), intent(out) :: F_string
    character(len=1, kind=C_CHAR), dimension(:), pointer :: p_chars
    integer :: i
    if (.not. C_associated(C_string)) then
      F_string = ' '
    else
      call C_F_pointer(C_string, p_chars, [huge(0)])
      do i = 1, len(F_string)
        if (p_chars(i) == C_NULL_CHAR) exit
        F_string(i:i) = p_chars(i)
      end do
      if (i <= len(F_string)) F_string(i:) = ' '
    end if
end subroutine
子程序C_字符串\u ptr_到F_字符串(C_字符串,F_字符串)
使用ISO_C_绑定
类型(C_PTR),意图(in)::C_字符串
字符(len=*),意图(out)::F_字符串
字符(len=1,kind=C_字符),维度(:),指针::p_字符
整数::i
如果(.not.C_关联(C_字符串)),则
F_字符串=“”
其他的
调用C_F_指针(C_字符串,p_字符,[大(0)])
i=1,len(F_字符串)
如果(p_chars(i)=C_NULL_CHAR)退出
F_字符串(i:i)=p_字符(i)
结束
如果(i)
您需要将sgtring length作为隐藏参数传递。
请看我的文章

我很困惑。Fortran 77(和Fortran 90)没有F2K C互操作功能。您的代码Fortran 77是以什么方式编写的?我也很困惑。Gfortran将代码编译为Fortran 2008和绑定(C)
接口是Fortran 2003。您必须显示正在接口的子例程和收到的错误消息。这非常重要。例如,
字符*(C\u CHAR)
在语法上不正确。您应该只使用
字符(kind=C\u CHAR)
并且不关心您的代码是F77还是F。大多数Fortran 77代码都是有效的Fortran 2008代码。您是对的,gfortran使用的是f2008标准,没有与f95标准的ISO_C_绑定给定的代码假定Fortran编译器以特定的方式(小写,尾随下划线)装饰其符号。这种约定远不是普遍存在的。隐藏字符长度的约定可能也会有所不同。它们确实有所不同。在gfortran中将其从int更改为size\t的修补程序已经准备就绪。我假设大量使用类似代码的无知询问者涌入。关于最后一段,只有在需要进行种类转换时才需要副本需要。如果需要,C_CHAR类型的延迟长度指针可以与C字符串占用的相同存储序列相关联。通过简单检查,wiki页面不使用延迟长度字符,可能是因为编写时缺少gfortran支持。@IanH,感谢您的观察。我已经修改了编辑并扩展了我的评论,以讨论关联而不是复制,这确实是在可能的情况下更可取的做法。