Has anyone converted a large (ours is 550,000 lines) program of Fortran 77 code to C++ ? What pitfalls did you run into ? Was the conversion a success ? Did you use a tool like for_c
( http://www.cobalt-blue.com/fc/fcmain.htm ) ? Was the resulting C++ code significantly faster or slower ?
views:
1795answers:
6I once used this: http://manpages.ubuntu.com/manpages/hardy/man1/f2c.html to convert a small fortran program to C. The conversion was successful. The code wasn't significantly complex to detect any kind of speed change.
Since your program is allot bigger I don't really know if everything is going to run like it did with me.
There are a lot of things to consider.
There are really two paths to take. One is to do a direct line by line conversion to c. By that I mean every fortran statement to an equalivant c statement.
The other path to take is a rewrite, and with 500k loc+ that would be much more work. With that kind of size, I certainly would look for a tool, to do the translation, like f2c.
Issues for a straight port...
gotos translate directly, you will need to create labels for the goto targets.
label10:;
goto label10;
Array subscripting is a potiential problem. c is zero based, fortran is 1 based, so arrays need to be dimensioned one larger in the fortran code.
real*4 a(10,20) becomes
#define XMAX 10 + 1
#define YMAX 20 + 1
float a[XMAX][YMAX];
allowing the loop to be written like this.
for (x = 1; x <= XMAX; x++)
for (y = 1; y <= YMAX; y++)
a[x][y] = 0.0f;
c array access is in row major order, while fortran is column major. that can be a performance problem. if it does become a problem, you may be able to solve it with some sort of macro definition which reverses the order or the array subscripts. In fact you could also have the macro subtract one off of each of the subscripts in order to make it look like a one based array, actually map to a zero based array.
real*8 a(XMAX,YMAX) a(4,2) = 3.14
#define A(X,Y) a[Y][X]
double a[XMAX][YMAX];
A(4,2) = 3.14;
fortran unit io can be simulated with stdio type files. if you are using unit 19, then
FILE *fp19 = fopen("file","mode");
There may be issues with carriage control if you are using fortran carriage control in your files. units 5 and 6 can be simply referenced with stdin, and stdout without fopen.
A lot of formats can be handled with the printf family of functions. You may have to add additional loops to deal with some of the fortran array io.
WRITE(20, 200) (PROJ(z,4),z = 1, 20)
int z;
for (z = 1, z <= 20; z++)
printf("%lf ", proj[z][4]);
o using f2c is probably the fastest way to do it. Then you are stuck with its rtl.
o doing a direct port is a feasable thing to do. Time consuming, but doable
o if you want to maintain it long term, I would recommend a rewrite. Very time consuming, probably faster, but more maintainable in the long run
Happily in any case you have the original program to use as a baseline to make a set of unit tests to help in the development effort.
This adds to EvilTeach's advice. Keep in mind that it's fairly easy to link Fortran 77 and C/C++ code, so you can convert parts of your application incrementally and link them together with the old parts. You'll have to think about all the usual fortran/c discrepancies (row/column-major arrays, array indexing, etc.) if you do this, but it would save you the pain of debugging your entire auto-translated codebase at once.
There are many large hybrid codes like this at the national (DOE) labs, which have a significant investment in old Fortran code. If you go this route, you might consider using Babel, which was developed to allow components to be shared between C, C++, Fortran, Fortran90, Python and Java all in the same app. The motivation for this at the labs is tying together physics models built by different teams for really large simulations, but you might find it useful for transitioning your code, too. It's actively maintained and used on a lot of projects, though it might be a bit too complex for what you're trying to do.
You might want to look into Promula. It produces more readable C code than many other automatic translators. I haven't used Promula directly, but I've converted a fair amount of Promula output from C to C++. It's easy to clean up the C code to legal C++, but of course it takes more effort to make it really good C++.
My reaction is why do you want to convert it.
The question of how to develop a product with a large Fortran code base was looked at by numerous companies in the 1990's. That is whether to convert, stay with Fortran or produce a hybrid. I think the majority opted for the hybrid approach, usually C++ for the user interface and the original Fortran code base in the background.
My suggestion is to look at "Mixed language programming using C++ and FORTRAN 77" by Carsten Arnholm available at http://arnholm.org/software/cppf77/cppf77.htm In the earlier days of the internet this document was well linked to.
This document describes how to have an application that contains C++ and Fortran. I cannot say whether some of the technical details may be outdated but this document came out of a project that wanted to using C++ for its development but had a huge Fortran code base.
You could also look at "Scientific and Engineering C++: An Introduction with Advanced Techniques and Examples" by Barton and Nackman, available from good book stores. This book teaches C++ for Fortran programmers. It has a few examples of writing wrappers to Fortran code from C++. It is a good C++ book ignoring the Fortran aspect. It was written before the standard was set but the differences are not very big.
I've worked on a application that, at its heart, was code converted from FORTRAN using for_c . The code it created was god awful. It was very difficult to maintain since most of it was indecipherable. Luckily that code was pretty stable and it was rare that anything had to be done to it.
However, this was done many years ago - circa the early 16-bit years of Windows. Maybe for_c is better now?