C++/FORTRAN 互操作中处理字符串的官方方法是什么

fan*_*ako 5 c++ string fortran fortran-iso-c-binding

我想了解 C++/FORTRAN 互操作性的最新改进,特别是在字符串方面。以下是我不成功的尝试,请帮助我纠正或建议更好的解决方案。我的编译器是 gcc 4.8.5

在 C++ 中

#include <iostream>

extern "C"{
    void SayHello(char*);
}
int main(int argc, char** argv){
    char * name = argv[1];
    SayHello(name);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在 Fortran 语言中

module MyModule

      contains
          subroutine SayHello(people) bind(c,name="SayHello")
              use, intrinsic :: iso_c_binding
              character, dimension(50), intent(in) :: people
              write(*,*) "Hello ", people
          end subroutine
end module MyModule
Run Code Online (Sandbox Code Playgroud)

Mat*_*t P 2

尝试使用c_char以下类型:

character(kind=c_char), dimension(*), intent(in)


编辑 1 所以,在 @francescalus 提出问题后,我进一步研究了这一点。基本上,“假定大小”字符数组不是必需的1,尽管我确实相信 char 数组的大小是(如果我错了,请纠正我)。我将在下面发布 C 调用 Fortran 版本,因为我不知道 C++ 语法,也不想查找它。


编辑2 正如脚注1中提到的,只有在Fortran程序中声明people为假定大小的字符数组,或者(如@VladimirF建议的)直接由 给出的大小才是正确的sz。我在下面的代码中清除了这一点。

Fortran 程序:

! SayHello.f90
subroutine SayHello(people,sz) bind(c,name="SayHello")
    use, intrinsic :: iso_c_binding
    implicit none
    ! Notes: 
    ! The size `sz` of the character array is passed in by value.
    ! Declare `people` as an assumed-size array for correctness, or just use the size `sz` passed in from C.
    character(kind=c_char), intent(in), dimension(sz) :: people
    integer(kind=c_int), intent(in), value :: sz
    write(*,*) "Hello, ", people(1:sz)
end subroutine
Run Code Online (Sandbox Code Playgroud)

以及 C 程序:

/*Hello.c */    
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void SayHello(char *name, int len);

int main(int argc, char** argv){
    size_t sz = strlen(argv[1]);
    char * name = malloc(sz+1);
    strcpy(name, argv[1]);
    SayHello(name, sz+1);
    free(name);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译(使用ifort)、调用和输出:

ifort /c SayHello.f90 
icl Hello.c /link SayHello.obj
Hello.exe MattP
// output: Hello, MattP
Run Code Online (Sandbox Code Playgroud)

1更新:似乎“为了互操作性”的官方用法是使用假定的大小声明为字符数组:char(len=1,kind=c_char), dimension(*), intent(in)

  • 您没有传递字符数组的大小(或字符标量的长度):“character(kind=c_char),intent(in) :: people”是一个标量长度为 1 的字符,没有“dimension”语句。在这种情况下,“people(1:sz)”是大于 1 的“sz”的无效子字符串引用(或者标量的无效数组引用)。 (2认同)