简体   繁体   中英

accessing variables of fortran module from c++

Currently I am working on a project that requires integrating fortran code to c++. In fortran module lots of variables and arrays are declared. I am able to access the integer,float and double types from c by declaring ac variable as extern double common_area_mp_rmax_ when the corresponding fortran declaration is real*8 rmax and the name of the module is common_area. However, when I try to do the same for an array I am getting error.

suppose the code in fortran module is: real*8,allocatable,dimension(:,:,:) :: x

I have cretaed ac double pointer as:

extern "C" { double* common_area_mp_x_; }

Now when I compile the whole project, it says "multiple definition of `variable_area_mp_x_'". I am using CMake to compile the whole project. Can someone shed some light what I am doing wrong? I am new to fortran and it is getting hard for me to fix this. I appreciate your time and help.

Thanks, mindbender

Fortran 2003 introduced interoperability with C into the standard Fortran language. Unless you have good reasons to the contrary, you should be using the facilities provided by this language feature. See the tag on this site for examples.

Under the current Fortran standard (and in the draft of the next standard revision), a Fortran allocatable module variable is not interoperable with a C variable.

In terms of implementation, the Fortran compiler will use a descriptor to store the allocation status of the allocatable variable. There is more to this descriptor than just a pointer to the data - see "Handling Fortran Array Descriptors" in the compiler's User and Reference guide for more information.

The best approach to sharing information in this case depends on what you are trying to do. One option is to give the allocatable array the TARGET attribute, and then have a separate variable of TYPE(C_PTR) with a binding label with the C address of the target. Aspects such as the size of the array would need to be communicated separately.

MODULE common_area
  USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_DOUBLE
  IMPLICIT NONE
  ...
  REAL(C_DOUBLE), ALLOCATABLE, TARGET :: x(:,:,:)
  TYPE(C_PTR), BIND(C, NAME='x_ptr') :: x_ptr
CONTAINS
  ! Call before operating on x_ptr in C++
  SUBROUTINE init
    USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_LOC
    ALLOCATE(x(1,2,3))
    x_ptr = C_LOC(x)
  END SUBROUTINE init

~~~

// After init has been executed, this is a 
// pointer to the value of the allocatable module variable
extern "C" double *x_ptr;

Given a C++ file test.cpp with contents

extern "C" { double * foo; }
extern double bar;
double asdf;

with gnu tools

g++ -Wall -c test.cpp; nm test.o
> 0000000000000000 B asdf
> 0000000000000008 B foo

ie using the first option actually introduces a new symbol with that name.

In this case the right choice would be

extern double * common_area_mp_x_;

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