Initialization of fortran common character variables from c


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
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kent OlsenDBACommented:

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 ();


egleyAuthor Commented:

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...

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.
Become a Certified Penetration Testing Engineer

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

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.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
egleyAuthor Commented:
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...

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,


It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.