Question

I'm trying to access an array within a Fortran common block structure from C++.
I have a mixed sample code with C++ and Fortran.

Fortran:

integer a(5),b  
common  /sample/ a,b  
a(1) = 1  
a(2) = 5  
a(3) = 10  
a(4) = 15  
a(5) = 20  
b = 25  

Then in C++:

extern "C"{  
    extern struct{  
        int *a,b;  
}sample_;  

From C++, if I try to print the value sample_.b:

printf("sample b:%d\n",sample_.b);

I get the value of a(2) : sample b:5

And if I try to print any other of the array-a values I just get a segementation fault...

printf("sample_.a[1]=%d\n",(int)sample_.a[1]);  
printf("sample_.a[0]=%d\n",(int)sample_.a[0]);

What am I doing wrong?¿ Any idea ¿?
I think, maybe I have to pass the length of the array "a" too to C++, but if so, I don't know how to do it either.

Was it helpful?

Solution

My Fortran is a bit (OK, QUITE a bit) rusty, but let me give it a whirl.

a probably received the VALUE rather than a pointer to it. That would set it to 1, which not a good pointer value.

b received the second value in the data block. Your C++ struct gives no indication to the compiler what the real format of the data is, so it's going to just mindlessly assign the items to the structure in the order given in the struct. I'd get a pointer to the data block and disassemble it by hand.

Assign a to the ADDRESS of the data block (as a long int pointer, looks like; your mileage may vary) and b = a[5]. Hope that helps.

OTHER TIPS

If you want to share global variables between C and Fortran, the best way is to use module variables and the Fortran ISO_C_Binding. Common blocks are a relic, best avoided unless part of legacy code. Using the ISO_C_Binding will make your code compiler and platform independent. There is a code example in the subsection "Interoperable Global Variables" of the chapter "Mixed Language Programming" of the gfortran manual. This isn't specific to gfortran, just some good documentation.

Continuing with the ISO_C_Binding, if you use the Fortran types that it provides you will be ensured of a match to the C types. The Fortran equivalent to C's int is C_INT. A list appears in the chapter "Intrinsic Modules" of the gfortran manual.

Looks to me like your FORTRAN data is actually laid out as

struct {
  int a[5];
  int b;
}

and you are on a machine where sizeof(int) == sizeof(int*).

thak you all for your useful anwers. Following your advices I finally realized what my problem was. I think my mistake was that in Fortran I had:

integer a(5),b  
common  /sample/ a,b  

a(5) with a fixed size, and then in C++:

extern "C"{  
    extern struct{  
        int *a,b;  
}sample_;  

*a without size, as a pointer. Thus, the compiler was understanding a this way, as a *int pointer instead of as an a(5) array

For a proper C++/Fortran code you should use at least Fortran 2003. It is actually quite straightforward to create a Fortran 2003/2008 interface for an old Fortran code (even for Fortran 77).

Here is a link to a post about mixing modern Fortran and C++:

http://solarianprogrammer.com/2012/05/11/mixed-language-programming-cpp-11-fortran-2008/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top