2

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 a c 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 a c 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

2
  • no actually I have the declaration in C side with extern. I will just edit and reduce that confusion.. thanks.. Commented Jan 22, 2016 at 2:57
  • Since it is only a basic variable (not a struct, function or a class), perhaps you could leave out double * common_area_mp_x_ from header files if necessary, and then declare extern double * common_area_mp_x_ in the C++ file where you reference that variable. Commented Jan 22, 2016 at 4:33

2 Answers 2

6

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;
Sign up to request clarification or add additional context in comments.

4 Comments

According to my test, the problem doesn't seem to be on the fortran side but in the use of extern "C" double * ptr when extern double * ptr should have been used in C++ code.
@J.J.Hakala From the Fortran side, BIND(C) on interoperable arguments makes the issue go away. There are other latent problems with the OP's approach. It is 2016... there are very few valid excuses for not writing standard conforming code for this sort of problem.
ah ok, I now read the fortran-iso-c-binding wiki more thoroughly.
thanks for the useful comments IanH and J.J. Halaka, I have tried using the fortran-iso-c-binding for a test program and it worked.. so I guess I will modify my code now to make it work.. thanks again..
2

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

i.e. 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_;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.