简体   繁体   中英

What is the official way to deal with string in C++/FORTRAN interop

I'd like to learn the latest improvement in C++/FORTRAN interoperability when it comes to string in particular. The following is my unsuccessful attempt, please help me correct or advise a better solution. My compiler is gcc 4.8.5

In C++

#include <iostream>

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

In 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

Try using the c_char type:

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


EDIT 1 So, after @francescalus posed the question, I looked into this further. Basically, the "assumed size" character array is not necessary 1 , although I do believe that the size of the char array is (please correct me if I'm wrong about that). I'm going to post a C-calling-Fortran version below, since I don't know the C++ syntax and don't feel like looking it up.


EDIT 2 As mentioned in footnote 1, it is only correct to declare people in the Fortran program as an assumed size array of chars, or (as suggested by @VladimirF) with the size given directly by sz . I clear this up in the code below.

The Fortran program:

! 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

And the C program:

/*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;
}

Compilation (with ifort), call, and output:

ifort /c SayHello.f90 
icl Hello.c /link SayHello.obj
Hello.exe MattP
// output: Hello, MattP

1 Update: Seems like the official usage "for interoperability" is to declare as an array of characters, using assumed size: char(len=1,kind=c_char), dimension(*), intent(in)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM