Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28591 Discussions

An example of passing a struct from C to FORTRAN

chris-sn
Beginner
3,271 Views

I found several fragments of examples, but I confess it took me a while to get everything in place for a complete working example. I offer this code to help anyone else in the same boat, and to invite corrections or improvements (in particular I'm not at all confident I am handling the character array well)

The FORTRAN piece is built into a static library and this is the essence of it (sorry for the mixed case!):

-------------------------------------------------------

subroutine ReceiveFromC(cstruct) BIND(C,name='ReceiveFromC')
USE, INTRINSIC :: ISO_C_BINDING
implicit none

TYPE, BIND(C) :: MYFTYPE
INTEGER(C_INT) :: I, J
REAL(C_FLOAT) :: S
real(C_DOUBLE) :: D
character(kind = C_CHAR, LEN =15):: T
END TYPE MYFTYPE

TYPE (MYFTYPE) :: cstruct

integer idum, jdum
real rdum
double precision ddum
character (15) :: TDUM
idum = cstruct.i
jdum = cstruct.j
rdum = cstruct.s
ddum = cstruct.d
tdum = cstruct.t

end subroutine

---------------------------------------------------
The C++ piece looks like this:

struct thecstruct {
int m, n;
float r;
double d;
char c[15];
};

extern "C" {void ReceiveFromC(thecstruct*); };

void Calculator::PassToFortran()

{
thecstruct *mycstruct = new thecstruct;
mycstruct->m = 11;
mycstruct->n = 12;
mycstruct->r = 1.5;
mycstruct->d = 2.5;
char* dum = "spacepadded ";
for (int i = 0; i<15 ; i++)
{
mycstruct->c = dum ;
}

ReceiveFromC(mycstruct);
delete mycstruct;

}

0 Kudos
6 Replies
Steven_L_Intel1
Employee
3,271 Views
Very good overall. I will observe that component T, being CHARACTER(15), is not "interoperable" according to the language. It should be an array of CHARACTER(1) elements just like it is in C. Perhaps at some point in the future the compiler will have the ability to complain about this. But if you did that, moving the data would be more complicated (use TRANSFER, I guess.)

I'll also ding you for using dot as a component separator instead of % in the Fortran.
0 Kudos
chris-sn
Beginner
3,271 Views
Thanks Steve (and for all your past help). My Fortran 2003 book arrived just after I got this working so hopefully less trial and error in the future!

I'm interpreting your comment on component T as meaning "this is going to work, but it's outside what the standard guarantees will work" - is that right?
0 Kudos
rase
New Contributor I
3,271 Views
Passing structures between Fortran and C/C++ (and back, of course) seems to be a minefield. Can someone provide advice where to find a good introduction and also advanced examples for passing structures, also the tricky ones, for example where components of the structure are allocated dynamically?
0 Kudos
Steven_L_Intel1
Employee
3,271 Views
chrissn, yes, what you have will work but is outside the standard.

rase, the whole idea of the C Interoperability features in Fortran 2003 was to eliminate that uncertainty. There are several textbooks on Fortran 2003 that describe these features, or you can read the standard - a link is on this forum's main page. I hope that most of these features will be documented for Intel Fortran in the next major release, but that will be reference information and not tutorial in nature.

I will comment that not everything you can express in C can be expressed in standard Fortran, and vice-versa. In the case of dynamic allocation, the type C_PTR is provided to be interoperable with a C pointer, but Fortran allocatable arrays are not interoperable, on their own, with C. The standard does provide such features as C_F_POINTER and C_LOC to convert between C pointers and Fortran pointers and these can be very powerful.
0 Kudos
chris-sn
Beginner
3,271 Views
As an aside to this discussion, it is relatively easy to arrange for a C++ program to directly read and write FORTRAN module variables. Having got that working, I felt (possibly wrongly) uncomfortable with the resulting coupling and so switched tack to passing down a struct.
0 Kudos
Steven_L_Intel1
Employee
3,271 Views
It's fine to use module variables for this purpose - adding BIND(C) to their declaration. This is supported by C Interoperability.
0 Kudos
Reply