fortran77,iso_c_binding和c string

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

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 90和target,指针说明符,但Fortran 77似乎没有这样的东西。 所以,上面的代码不编译。

BIND(C)强制参数c_message为大小1.如何访问c_message字符串的其他元素?

编译:GCC 4.8.2

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

我曾经使用的所有Fortran 77实现都提供了与C互操作的特定于实现的机制。通常这些涉及C端知道Fortran编译器使用的名称修改和参数传递约定,并在接口上使用它们。 海湾合作委员会制度的惯例并不难以使用。

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

您有几个可互操作的替代方案,用于提供接受C char数组的面向C的接口。 也许最清楚的是接受Fortran假定大小的character数组:

 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端数组指针可能为空,则后者是必需的。 如果不能依赖该数组为空终止,则两者都需要传递显式长度。

无论如何,如果你最终想要一个长度大于1的Fortran character变量(而不是一个大于1的数组),那么可互操作的接口不能直接提供 – 这些类型不属于那些C互操作规定适用。 除非你可以依赖默认字符类型为c_char ,否则你需要将它们与copy-in(/ copy-out)结合起来,以便在各种类型之间转换字符。 使用前一个接口,应该很明显如何将数组复制到长度大于1的Fortran标量character 。对于指针变体,使用如下的转换函数可能很有用:

 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 

(源自Fortran Wiki的C_interface_module的C_F_string_ptr子例程)

另一方面,如果您可以(或者无论如何)依赖于默认字符种类c_char那么您还有另外一种选择。 您可以有用地使字符数组(如第一个示例中的参数)与默认类型和长度大于1的标量字符对象相关联。 特别是,如果包装函数的伪参数是具有假定长度的标量字符,或者固定长度不超过数组元素的数量,则可以依赖参数关联将其与包装器中的字符数组相关联。 换句话说,在这种情况下,您只需将数组作为实际参数传递即可。

  SUBROUTINE FCODE(STR, N) CHARACTER*(*) STR INTEGER N WRITE(*,*), STR, N END void foo(char *str) { int N = 10; printf("Calling fortran\n"); fcode_(str, &N, strlen(str)); } 

您需要将sgtring长度作为隐藏参数传递。 请参阅我的文章http://www.malcolmmclean.site11.com/www/MpiTutorial/CandFortran77.html