Reputation: 1
I am trying to define and declare a set of structures in C, then interact with them in fortran before passing them back off to be manipulated in C functions. I understand that interoperability can be achieved through use of c structures and fortran common blocks. I have tried a few methods with no success.
Limitations: Using cvfortran, f77. It is not realistic to convert to newer formats. For C, using MSVS C compiler.
Here's the suggestion from the cvfortran manual, page 618: (http://jp.xlsoft.com/documents/intel/cvf/cvf_pg.pdf)
"As an example, suppose your Fortran code has a common block named Really, as shown:"
!DEC$ ATTRIBUTES ALIAS:'Really' :: Really
REAL(4) x, y, z(6)
REAL(8) ydbl
COMMON / Really / x, y, z(6), ydbl
"You can access this data structure from your C code with the following external data structure:"
#pragma pack(2)
extern struct {
float x, y, z[6];
double ydbl;
} Really;
#pragma pack()
Whenever I try this, I get an error for "Unresolved external symbol _Really refereced in function xxx, and it doesn't compile.
Method in CVFortran Manual:
Fortran
PROGRAM MYPROG
!DEC$ ATTRIBUTES ALIAS:'Really' :: Really
REAL(4) x, y, z
COMMON / Really / x, y, z
INTERFACE
SUBROUTINE STRUCTFUN()
cDEC$ ATTRIBUTES C, ALIAS:'_StructFun' :: STRUCTFUN ! for calling C functions
END SUBROUTINE STRUCTFUN
END INTERFACE
X = 6.
Y = 5.
Z = 0.
CALL STRUCTFUN()
END PROGRAM
C
#include <stdio.h>
void StructFun(void)
{
#pragma pack(2)
extern struct {
float x, y, z;
} Really;
#pragma pack()
printf("x: %f\n y: %f\n z: %f\n", Really.x, Really.y, Really.z);
printf("From C \n");
}
So then I tried what I have pasted below, in which I define a struct type in the header file, and then try to make it external to c. I should also mention that I am exporting the C function as a dll with a .def file so that it can be called from my fortran module. This gives no errors but returns values of zero for all of my variables.
Sample program:
Fortran
PROGRAM MYPROG
REAL(4) X,Y,Z
COMMON / REALLY / X, Y, Z
INTERFACE
SUBROUTINE STRUCTFUN()
cDEC$ ATTRIBUTES C, ALIAS:'_StructFun' :: STRUCTFUN ! for calling C functions
END SUBROUTINE STRUCTFUN
END INTERFACE
X = 6.
Y = 5.
Z = 0.
CALL STRUCTFUN()
END PROGRAM
C function
#include "structProg.h"
rtype really_;
void StructFun(void)
{
printf("x: %f\n y: %f\n z: %f\n", really_.x, really_.y, really_.z);
printf("From C \n");
}
C header file
#include <string.h>
#include <stdio.h>
typedef struct{
float x;
float y;
float z;
} rtype;
extern rtype really_;
extern void StructFun(void);
I know it's a stretch to ask this since I'm using an old compiler, but any guidance would be appreciated.
I've also tried a method listed here: http://www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html
Upvotes: 0
Views: 1270
Reputation: 180181
Your updated question presents a different problem than the original one did. Now the issue is:
This gives no errors but returns values of zero for all of my variables.
That's because you are not accessing the common block at all. Notwithstanding the external declaration of object really_
in your header file ...
extern rtype really_;
... your .c source contains a definition of object really_
on account of this:
rtype really_;
That's technically a "tentative definition", but there being no definition with an initializer in the same translation unit, the designated object is defined in that TU, and initialized with all members 0. It should therefore be no surprise that your C code prints out those zeroes.
Moreover, it's unclear why you expect to be able to access the Fortran common block REALLY
via the name really_
. Neither the specific example you've presented from the CVF docs nor the broader text of those docs supports that conclusion. There being no alias for that block declared on the Fortran side, the docs lead me to expect that it would be accessed on the C side via the all-uppercase version of its name, REALLY
:
extern struct {
float x;
float y;
float z;
} REALLY;
void StructFun(void) {
printf("x: %f\n y: %f\n z: %f\n", REALLY.x, REALLY.y, REALLY.z);
printf("From C \n");
}
Note in particular that
typedef
a structure type for the common block. Given the nature of the data, though, it seems more natural to me not to do so.REALLY
(as an external object), not a definition.REALLY
to a header file. That would be appropriate if you're going to access it from multiple C translation units, but unnecessary if you're only going to use it in one.Upvotes: 1
Reputation: 25286
I am no guru here, but the error is indicative of that there is not an integrated "C and Fortran" program.
You develop some modules in Fortran and some modules in C (C++). You decide whether it will be a C program (and then has main
as program entry point) or a Fortran program (and then it has the Fortran program entry point).
You compile the C modules and the Fortran modules with their respective compilers. These deliver .obj or .o files, object files. Finally you link these together to create the executable program.
What you did seems correct. But the "Unresolved external symbol" error is a linker error. It means the linker could not find the Fortran Common block in the object modules.
I hope this helps.
Upvotes: 0