Operating System - OpenVMS
1753760 Members
4784 Online
108799 Solutions
New Discussion юеВ

Re: Access Fortran module from C

 
SOLVED
Go to solution
Michael Menge
Frequent Advisor

Access Fortran module from C

How can I access a Fortran data module from C?

MODULE test
IMPLICIT NONE
SAVE
INTEGER*4 a1
INTEGER*4 a2
REAL*4 b1
END MODULE test

In the VMS Fortran User Manual there is an example how C and HP Fortran code can access common block of data:

The C structure
struct s
{
int a1;
int a2;
float b1;
} test;

works with an common block like

COMMON /test/ a1,a2,b1

but when using the module, the linker finds the symbols but the C program doesn't have the right addresses for the variables a1, a2 and b1.


10 REPLIES 10
Steven Schweda
Honored Contributor

Re: Access Fortran module from C

As usual, it might help if you showed actual
code, with actual build commands, and with
actual results.

> [...] the C program doesn't have the right
> addresses for the variables a1, a2 and b1.

And you determined this how, exactly?
Steven Schweda
Honored Contributor
Solution

Re: Access Fortran module from C

Also, as usual, it might help if you
explained the actual problem which you are
trying to solve, instead of asking how to
implement what may be a sub-ideal "solution"
to that problem.

I haven't used Fortran much since it was
still FORTRAN, before it got all fancy and
stuff, so I've never fired a MODULE statement
in anger before, and so I know nothing, but
between the Language Reference Manual and
/LIST and /MAP, I did get the following to
do something which might be slightly
interesting:

alp $ type test_mod.for
MODULE test
IMPLICIT NONE
SAVE
INTEGER*4 a1
INTEGER*4 a2
REAL*4 b1
END MODULE test

alp $ type test_main.for
C Module test program -- Fortran calls C.

program test_main

use test

a1 = 1
a2 = 2
b1 = 1.0

print *, a1, a2, b1
call mod_c
print *, a1, a2, b1

end

alp $ type mod_c.c
extern int $test$a1;
extern int $test$a2;
extern float $test$b1;

void mod_c( void)
{
$test$a1 = 51;
$test$a2 = 52;
$test$b1 = 51.;
}

alp $ fort test_mod
alp $ fort test_main
alp $ cc mod_c
alp $ link test_main, test_mod, mod_c
alp $ run test_main
1 2 1.000000
51 52 51.00000

Again, knowing approximately nothing about
what you're actually trying to do, I have no
real idea if that's at all useful.

Note that with the info provided here, you
should be able to reproduce my results. You
should be able to say that, too, about your
own questions.
Joseph Huber_1
Honored Contributor

Re: Access Fortran module from C

Steven has shown how scalar variables in a module can be accessed by their global symbols as $module$name.
But those scalars are not structures to be used in Your C procedure, and their allocation order and alignment is defined by the compiler internals.

If You want to pass a structure to a C procedure, You have to somehow pass its address to the C procedure, e.g. as an argument, if You want to avoid commons.

Example:
Fortran module test_mod.f90:

MODULE test
IMPLICIT NONE
structure /test_mod/
INTEGER*4 a1
INTEGER*4 a2
REAL*4 b1
end structure
END MODULE test

C procedure mod_c.c:

struct test_mod
{
int a1;
int a2;
float b1;
};

void mod_c(struct test_mod *t) {
t->a1=10; t->a2=20; t->b1=20.0;
}

Fortran main test_main.f90:

program test_main

use test

record /test_mod/ t
t.a1 = 1
t.a2 = 2
t.b1 = 1.0

print *, t
call mod_c(t)
print *, t

end

Fortran test_mod
Fortran test_main
cc mod-c
link test_main,test_mod,mod_c
run test_main
Result
1 2 1.000000
10 20 20.00000

http://www.mpp.mpg.de/~huber
Mike Kier
Valued Contributor

Re: Access Fortran module from C

First, let me echo all that Steven wrote - you would do well to share listings and map files and be explicit about what you are attempting to solve and what the variance from what you expected is.

That said, please remember that variables in a MODULE are not a 1-for-1 replacement for a named COMMON. There is no sequencing or ordering of data layout - the compiler and linker are free to place the actual individual data elements anywhere at all - so a struct is not likely, no matter what compile-time alignment/padding options are chosen, to map to a real*4 and two integer*4 variables laid out sequentially.

You could possibly get close to it if there was a TYPE definition with SEQUENCE with the three data elements within it - or use the non-standard STRUCTURE/RECORD similarly.

But one of the reasons Fortran introduced MODULE in the 1st place was to break the requirement for knowledge of the underlying physical memory layout.
Practice Random Acts of VMS Marketing
Joseph Huber_1
Honored Contributor

Re: Access Fortran module from C

If You can't modify the C procedure passinf the fortran structure as an argument, a PUBLIC structure definition in the fortran module can also be used:
test_mod.f90:

MODULE test
IMPLICIT NONE
structure /test_mod/
INTEGER*4 a1
INTEGER*4 a2
REAL*4 b1
end structure
public
record /test_mod/ public_mod
END MODULE test

mod_c.c:

struct test_mod
{
int a1;
int a2;
float b1;
};

extern struct test_mod $test$public_mod;


void mod_c() {


$test$public_mod.a1=10;
$test$public_mod.a2=20;
$test$public_mod.b1=20.0;

}

test_main.f90:
program test_main

use test

public_mod.a1 = 1
public_mod.a2 = 2
public_mod.b1 = 1.0

print *, public_mod
call mod_c()
print *, public_mod

end

http://www.mpp.mpg.de/~huber
John McL
Trusted Contributor

Re: Access Fortran module from C

C is pass by value or by reference (i.e. pass address), Fortran is almost always pass by reference.
John Gillings
Honored Contributor

Re: Access Fortran module from C

Michael,

I think you need to provide more information here. What code do you have? What can be changed? What cannot? Why is it necessary to share data directly? (I find that "naked" data structures are a mistake, even between modules in the same language).

Although OpenVMS was specifically designed to allow development of programs in multiple languages, it's not always the most optimal approach.

Most of the time you would only attempt it if you have two large chunks of code in different langauges and want to use them together, without recoding one in the other language.

Cross language procedure calls are relatively simple - it's just a matter of getting the order, data type and passing mechanism of arguments to match up. However, cross mapping DATA can be a problem. Apart from the obvious issues of alignment, there are more obscure issues. For example, note that, in theory, a C compiler is allowed to reorder fields within a structure. Forcing specific fields to be in specific places can be a problem. Code should be written so that it does NOT depend on data adjacency.

One approach may be to convert a data interface into a procedural one. For example, define routines a1, a2 and b1, each with an optional argument. Always return the corresponding data value, and the argument is present, set the value. That can make the object look like a variable, but eliminates the issue of data mapping.

x=a1(); -- fetch the value of a1 into x
a1(y); -- set a1 to y

A crucible of informative mistakes
Michael Menge
Frequent Advisor

Re: Access Fortran module from C

Our MIP optimizing source consists of more than 120 fortran routines and many data is hold in about 20 modules (variables, structures, arrays, also allocatable structures and arrays, linked lists etc., so no common blocks). The system has an input, modelling (generating the matrix), solving and output part.
Now the modelling part will be written in FLOPC++ and for the solving part we will use a standard MIP solver like CPLEX, Gurobi or Xpress. The question was, how to access from C/C++ the data the fortran routines read in and save in the data modules.
Steven's reply shows how to access the data in a fortran module, it works fine.
Using upper and lower characters in variable/structure/array names you have to look at the resolution of global symbols in linker and debugger too.
Hoff
Honored Contributor

Re: Access Fortran module from C

SDL can simplify the maintenance of this stuff.

SDL (in this case) is the Structure Definition Language, and it allows you to have one source file with the structures and related, and to use SDL compiler to create language-specific include files.

It'll be work to get to SDL, but it'll repay you by avoiding the effort involved in tracking and updating the various programs accessing your data structures; from having to keep the source code of all of your different programs all in synchronization as the data structure definitions shift.

SDL is on the Freeware.