Article View: comp.lang.fortran
Article #4627Re: How to link Fortran with c++ ??
From: Carsten Arnholm
Date: Wed, 31 Jan 1996 14:42
Date: Wed, 31 Jan 1996 14:42
186 lines
6402 bytes
6402 bytes
Niels Hilbrink <Niels@imacsg1.epfl.ch> wrote:
>Hi,
>
>I have to link a piece of fortran code with c++ code but since if never
>done that before I'd like to know a) can it be done and b) is it
>difficult.
>
>Everything concerning this subject is welcome.
>
>Gr.
>Niels Hiblrink
>
>
>--
>
> The most overlooked advantage to owning a computer is
> that if they foul up there's no law against wacking
> them around a little.
>
>------------------------------------------------------------
>Koen D'Hondt Niels Hilbrink
>koen@@dutlhs1.lr.tudelft.nl niels@dutlcc3.lr.tudelft.nl
>
>**** Ripley Software Development ****
>(finger niels@dutlcc3.lr.tudelft.nl for more information.)
>------------------------------------------------------------
Hi there,
Mixed language programming (C++/FORTRAN 77) is not as hard as
it may seem.
The only non-trivial problem you must solve is fortran CHARACTERs.
You need to write a minimal CHARACTER class in C++.
If you require single-source portability, it becomes slightly
more complicated, but not impossible.
Below follows a summary of some stuff that I have done, plus
some additional thoughts.
typedef int INTEGER;
typedef float REAL;
typedef int LOGICAL;
#include "character.h" // CHARACTER class (see below)
#define SUBROUTINE extern "C" void __stdcall
#define INTEGER_FUNCTION extern "C" INTEGER __stdcall
#define REAL_FUNCTION extern "C" REAL __stdcall
The CHARACTER class may look something like this:
#include <string.h>
/*
class CHARACTER
===============
A minimal class used when passing C-string arguments from C++ to
FORTRAN 77 (received as FORTRAN 77 CHARACTER strings), and subsequently
returned back to C++ as properly zero terminated c-strings.
Method used for zero-termination:
=================================
When the CHARACTER destructor is activated (typically when the
CHARACTER object goes out of scope within a C++ stub function)
the zero-termination of the c-string is automatically managed.
FORTRAN Assumptions:
====================
(1) FORTRAN truncates assigned strings when CHARACTER variable is too short
(2) FORTRAN pads CHARACTER variable with blanks when assigned string is short
(3) FORTRAN represents a CHARACTER as a string pointer followed by a length
Author: Carsten A. Arnholm, 20-AUG-1995
*/
class CHARACTER {
public:
CHARACTER(char* cstring) : rep(cstring), len(strlen(cstring)) {};
CHARACTER(char* cstring, const size_t lstr);
~CHARACTER();
public:
char* rep; // Actual string
size_t len; // String length, used by FORTRAN intrinsic function LEN()
};
inline CHARACTER::CHARACTER(char* cstring, const size_t lstr) : rep(cstring), len(lstr-1)
{
size_t actual = strlen(rep);
for(size_t i=actual;i<len;i++) rep[i]=' ';
rep[len]='\0';
}
inline CHARACTER::~CHARACTER() {
for(size_t i=strlen(rep)-1;i>=0;i--) {
if(rep[i] != ' ') {
rep[i+1] = '\0';
break;
}
}
}
now you can declare FORTRAN subroutine prototypes in C++:
SUBROUTINE MYSUB(INTEGER& I1, CHARACTER C1, INTEGER& I2);
To create a portable solution, do the following:
a) Write header files for your FORTRAN libraries as shown above.
b) Compile FORTRAN code and create *.lib files.
c) Include the FORTRAN library header files in your C++ code.
d) Call FORTRAN according to above prototype example.
e) Compile C++ code and link with FORTRAN libraries
f) This executes directly for Visual C++ 2.1 & 4.0 in combination
With Fortran Powerstation
porting to other machines:
a) Leave C++ and Fortran code untouched (single source requirement!)
b) Write a small C++ program that read your FORTRAN library header files,
and generate:
b.1: a platform-specific header file for the fortran
library. Here you deal with upper/lowercase names,
trailing underscores, character lengths etc.
b.2: a platform-specific *.CPP file containing inline
functions that convert from
MYSUB(INTEGER& I1, CHARACTER C1, INTEGER& I2)
to
mysub_(int& I1, char* C1.rep, int& I2, int C1.len)
(example above is for for SGI)
c) Compile & link this generated code with your application.
e) Should execute on basically any platform (UNIX, VMS, ...)
Other issues
============
a) Calling/linkage convention (C++).
This is taken care of through the use of the statement: extern "C"
This avoids name mangling which is not used in FORTRAN.
b) Routine names
An ANSI standard FORTRAN routine name should be defined in UPPERCASE
and max 6 characters. This does not, however, mean that the name
used when calling from C/C++ should be in uppercase. On the SGI machine
(i.e. unix) the routine must be in lowercase with a trailing underscore.
On other unix boxes, you may need a leading underscore and/or uppercase
name.
Example:
FORTRAN : SUBROUTINE MYSUB
Machine-dependent C++ prototype (SGI): extern "C" void mysub_();
c) Parameter types and argument passing
FORTRAN will always require parameters to be passed by reference
FORTRAN : SUBROUTINE MYSUB(IVAL)
INTEGER IVAL
Machine-dependent C++ prototype (SGI): extern "C" void mysub_(int& IVAL);
d) Machine dependent comparison of language types:
FORTRAN C++
======= ===
INTEGER int&
REAL float&
LOGICAL int&
CHARACTER char* (+ size_t length )
DOUBLE PRECISION double&
good luck,
Carsten Arnholm
ca@sesam.dnv.no
Technical Details
Message-ID:
<4env5h$3ai@nms.telepost.no>Path:
arc1-ca.pugleaf.net!telepost.no!usenetReferences:
<310DD74F.59E2@imacsg1.epfl.ch>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!telepost.no!usenet From: Carsten Arnholm <ca@sesam.dnv.no> Newsgroups: comp.lang.fortran,comp.lang.c++ Subject: Re: How to link Fortran with c++ ?? Date: 31 Jan 1996 14:42:57 GMT Organization: DNV Message-ID: <4env5h$3ai@nms.telepost.no> References: <310DD74F.59E2@imacsg1.epfl.ch> NNTP-Posting-Host: hugin.sesam.dnv.no Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 1.1 (Windows; I; 32bit)