fortran pass character*81 array to c/c++ code

匿名 (未验证) 提交于 2019-12-03 02:38:01

问题:

I am a fresh in programming, I wanna to call a fortran function in my c++ code. the thing is I dont know how to pass a fortran character*81 array to my c++.

fortran code is like:

subroutine func01(a)     implicit none     character*81 a(2)     write(*,*) a(1)     write(*,*) a(2) end 

c++ code is like:

#include <iostream>  extern "C"{     void func01_( const char **a ); }      int main() {     const char *a[2];     a[0]="Hello world!";     a[1]="This is a test!";     func01_(a);     return 0; } 

I bascially tested my fortran code using this

program pro01     character*81 a(2)     a(1)='Hello world!'     a(2)='This is a test!'     call func01(a) end program pro01 

'func01(a)' works well.

thanks to @PaulMcKenzie, I corrected some fool problems.....

However, when i compiled cpp code, the result went like messy codes like:

what should I do?

回答1:

The following code seems to work for gcc4 on Linux(x86_64), but it is not clear whether it is also valid for other platforms. (As suggested above, C-interoperability of modern Fortran may be useful.)

func01.f90

subroutine func01( a )     character(*) :: a( 2 )     print *     print *, "char length = ", len(a(1)), len(a(2))     print *, "raw a(1) : [", a(1), "]"     print *, "raw a(2) : [", a(2), "]"     print *, "trim     : [", trim(a(1)), "] [", trim(a(2)), "]" end 

main.cpp

extern "C" {     void func01_( char *c, const int len ); }  #include <iostream> #include <cstring>  // for memset() int main() {     const int lenmax = 30, numstr = 3; // changed char length to 30 to fit in the terminal     char a[ numstr ][ lenmax ];     std::string str[ numstr ];      str[0] = "moon"; str[1] = "mercury"; str[2] = "jupiter";      for( int k = 0; k < numstr; k++ ) {         memset( a[k], ' ', lenmax );  // fill space                                                       str[k].copy( a[k], lenmax );  // copy at most lenmax char (no \0 attached)                             }      func01_( a[0], lenmax );     func01_( a[1], lenmax ); // pass from mercury     return 0; } 

Compile

$ g++ func01.f90 main.cpp -lgfortran 

Result

char length =           30          30 raw a(1) : [moon                          ] raw a(2) : [mercury                       ] trim     : [moon] [mercury]  char length =           30          30 raw a(1) : [mercury                       ] raw a(2) : [jupiter                       ] trim     : [mercury] [jupiter] 


回答2:

Here is a portable solution to pass an array of arbitrary length strings from C to Fortran.

I used a C++ file very similar to your own:

#include <iostream>  extern "C" void func01(const char **a);  int main() {   const char *a[2] = {"Hello World","This is a test"};   func01(a);   return 0; } 

The only changes above are the initialization of the character arrays and removing the not-so-portable underscoring of the Fortran function. Instead we will be using standard C interoperability provided by Fortran 2003. The Fortran implementation of func01 becomes:

subroutine func01(cstrings) bind(C,name="func01")   use, intrinsic :: iso_c_binding, only: c_ptr, c_char, c_f_pointer   implicit none   type(c_ptr), dimension(2), target, intent(in) :: cstrings   character(kind=c_char), pointer :: a1(:), a2(:)    ! size_t strlen(char * s);   interface      function strlen(s) bind(C, name='strlen')        use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t        implicit none        type(c_ptr), intent(in), value :: s        integer(c_size_t) :: strlen      end function strlen   end interface    call c_f_pointer(cstrings(1), a1, [strlen(cstrings(1))])   call c_f_pointer(cstrings(2), a2, [strlen(cstrings(2))])   write (*,*) a1   write (*,*) a2 end subroutine func01 

The bind attribute is what gives us interoperability with C for the function name and we are using C types for variables. The variable cstrings will take an array of 2 pointers, or in C, *[2] or **. The bulk of the procedure is an interface block which lets us call the standard C library routine strlen to make our life easier with the following calls to c_f_pointer which translates a C pointer to a Fortran pointer.

When compiled and run, the output, as expected, is:

$ ./string-array-test  Hello World  This is a test 

Compiled and tested with gcc 5.1.0.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!