Initialization of fortran common character variables from c

Posted on 2003-11-14
Last Modified: 2013-11-08

For enhancing portability I am attempting to modify this inherited piece of fortran and c software to change from passing char *'s to fortran from a c function, and instead initializing character variables (in the c code) stored in common on the fortran side.

If you have a better way, please suggest. I thought this might be the best way to avoid all of the portability issues that I have come across. Some systems pass an int at the end of the argument list, some long ints, it core dumps on the sun at the call, seems to be OK on linux, but in general the thing is a constant source of pain; hence, the reason I'm trying to change it.

I thought that if I created a struct declared as extern with the same name as the common block in the fortran code, that I could then initialize the character variables in fortran common from within the c code via the struct of the same name. This works for int's, floats, etc..

Don't ask or suggest doing it on the fortran side. I wish I could. This thing also uses lex and yacc to parse the input deck, and the initialization of all the variables is done via lex, yacc and c. I know nothing of lex and yacc. I wouldn't even attempt to change the parsing over to fortran.

So initialization of the variables from the input deck has to be done within c, and I have to then initialize fortran common. As I said it's working fine for int's and floats, etc. The original author elected to not do this for strings, hence, the reason I'm  asking this question here.

THe compiler is accepting it, and I can print out the values of the strings on the c side, but when I go to the fortran side they have garbage in them. So, as an example, say I have a struct named 's'.     And a common of the same name on the fortran side. On the fortran side I have a character array of a large size, say string. ON the c side the 's' struct has string as a member and is declared as a char *.

On the c side I do

       c.string = something from the lex/yacc parser.

I printf it out and can see that it is set correctly.

But on the fortran side, if I print out the value of string it's got garbage.

Anyone have any ideas, or have a better suggestion?

Thanks very much,
Skip Egley
Question by:egley
LVL 45

Expert Comment

Comment Utility

Hi Skip,

This is a tough one.  (Which also makes it interesting....)

I would be very surprised if you can define fortran variables in labelled common and get to them directly from C.  The label name acts as a qualifier in a way that just isn't supported in C.

But that doesn't mean that it can't be done!

On the C side, can you define a struct that matches the common block description?  Then write a small assembler function that simply returns the address of the labelled common block.  My x80 assembler is horrible or I'd write it for you, but it seems that a simple function would do.

struct TCommonBlockA *CommonBlockA;
struct TCommonBlockB *CommonBlockB;

CommonBlockA = GetCommonBlockAAddress ();
CommonBlockB = GetCommonBlockBAddress ();



Author Comment

Comment Utility

THanks Kent.

THe compilers I've had the pleasure to come across (which isn't that many) have all supported the equivalent of named common blocks via structs. That is how the original author of this code is initializing all of the other fortran common coming from the input parser.

But I notice that none of them have strings. He had been passing the strings through the calls, which was/is giving me all kinds of portability problems, because the compilers don't handle them the same. Some times it simply doesn't appear to work. I can't be quite sure, the thing just core dumps. And of course everything runs fine when debugging is on. But try the simplest optimization and it crashes and burns. THis thing without optimizations is useless.

I have to find another way...

LVL 11

Expert Comment

Comment Utility
Many of the C compilers push their parameters on the stack back to front.  In Fortran, it is normally front to back.  Also, in C, the caller normally manages the stack whereas in Fortran, the called routine manages the stack.  You've done well to get past that lot.

How about using char [] instead of char*?  You are probably seeing a pointer address which is garbage instead of real data.
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

LVL 22

Accepted Solution

grg99 earned 500 total points
Comment Utility
There's no standard way that FORTRAN compilers use for labeling common blocks.  Some use external symbols, some use segment names.  There's no easy way to make this portable by using structs.

What I would do is write a little glue routine, either in FORTRAN or in C, that passes the variables to the other side.
For example, something like:

COMMON /ALLTHEVARS/X(1000),Y(1000),NAMES(1000)


oops, that's going from FORTRAN to C, I see you mostly want to go the other way:

float getmearrayx( int Index ) { return( X[ Index ] ); }

... and so on.....

If you have a lot of variable sto pass, you could try passing more than one  back at a time, but this gets into array order issues.
If you haev the time, just pass back the elements one at a time as we do above.

For passing thru characters, you can do it the same way, a character at a time is best to avoid string format issues.

Author Comment

Comment Utility
Thanks grg99,

Although not elegant (doubt if one can be elegant in this situation), I think your solution is best.

Could you explain to me what you mean by 'some use external symbols, some use segment names'? I'm not a compiler guy.

I continued on in the spirit of structs and named common, by storing them as 'signed char' and declaring them as one byte integers in fortran, then calling a fortran routine to convert these to strings. It's working, but your comment has me worried that this may not be portable either...

LVL 22

Expert Comment

Comment Utility
At the linker's level, most linkers aloow a compiler to say "put these data bytes in an area we will call "_DATA"",
put these code bytes in an area named "_CODE", and so forth.   Many FORTRAN compilers map common  block names to linker segment names.
In C, some compilers have #pragmas that let you direct code or data to a particular linker segment.  So you might get away with:

/This is C:
#pragma data("XX")

int X[1000], Y[1000];

... which *might* map right onto the FORTRAN common block:

COMMON /XX/ X(1000), Y(1000)


But mapping multi-dimensional arrays can be a problem, as FORTRAN usually IIRC stores arrays in row-first order, most other languagesw do it the other way.   Also char arrays I have no idea how FORTRAN stores them.

Good luck,



Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Windows Script Host (WSH) has been part of Windows since Windows NT4. Windows Script Host provides architecture for building dynamic scripts that consist of a core object model, scripting hosts, and scripting engines. The key components of Window…
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now