Mixing MS C/C++ with MS FORTRAN--MS-DOS Applications

Last reviewed: July 17, 1995
Article ID: Q85317
The information in this article applies to:
  • Microsoft FORTRAN for MS-DOS, version 5.1
  • Microsoft C/C++ for MS-DOS, version 7.0

SUMMARY

It is possible to use Microsoft C/C++ version 7.0 to make calls to Microsoft FORTRAN version 5.1. Microsoft C/C++ can issue calls to FORTRAN subroutines or functions, directly from the body of the C/C++ program or from the classes defined or derived. If the FORTRAN functions are included as member functions, they must be wrapped with a C++ member function first; that is, a C++ function should call the FORTRAN code because FORTRAN does not support the calling conventions used in C++ member functions.

The call to the FORTRAN language can be issued in the CONSTRUCTOR, DESTRUCTOR, or member function definition section. Although FORTRAN or C functions cannot be overloaded for different kinds of argument types and numbers of parameters, a member function of the CLASS object can be overloaded, and this overloaded function will in turn call the appropriate FORTRAN function that matches the arguments.

MORE INFORMATION

When linking with the Microsoft C/C++ 7.0 compiler, the FORTRAN run-time library must be a C-compatible version. The following link response-file should be used:

   LINK  @CPPFORT.LNK

CPPFORT.LNK

CPPMAIN.OBJ FORTRAN.OBJ CPPTEST.EXE NUL /NOD /NOE LLIBCE.LIB LLIBFERC.LIB OLDNAMES.LIB;

Note: CPPMAIN is the C/C++ object module(s), and FORTRAN.OBJ is the FORTRAN object module(s). LLIBCE.LIB and OLDNAMES.LIB are the run-time libraries for the C/C++ code, and LLIBFERC.LIB is the C-compatible FORTRAN run-time library. Alternatively, LLIBC7.LIB and LLIBF7RC.LIB can be used (where LLIBF7RC.LIB is C-compatible).

Is important to note the order in which the libraries are listed; the C/C++ libraries MUST be listed first, followed by the FORTRAN library, followed by any third-party library or user-defined library. If this order is not followed, there will be a number of multiply defined symbols coming from the C/C++ run-time library. It is also required to use the linker provided with the C/C++ compiler. The linker provided with the FORTRAN 5.1 compiler does not support the format for the C/C++ run-time library; if used, it generates an Invalid Object Module error on the C/C++ object files, because older versions of LINK do not understand the information used for C/C++ object files.

Below is a sample C++ program that defines a class COMPLEX for manipulating complex numbers. The class invokes a FORTRAN function for calculating the complex number. Note that the FORTRAN function has been declared with the EXTERN "C" attribute to prevent the C++ compiler from generating the call to the FORTRAN functions using C++ naming conventions.

Sample Code 1

#include <iostream.H>

typedef struct tagCOMPLEXNUM
  {
   float real;
   float imag;
  } COMPLEXNUM;

extern "C"
  {
   extern void __fortran CmpRoot (COMPLEXNUM * num);
  }

class Complex
  {
   public :
       //  Class constructors
     Complex ();                  // Default constructor
     Complex (float r, float i);  // Constructor with arguments

       //  Class member functions
     friend Complex operator+(Complex A, Complex B);
     Complex SqRoot ();           // Square root of a complex
     void display () const;       // Show formatted complex number

       //  Private data members
   private :
     COMPLEXNUM num;
  };

Complex Complex::SqRoot ()
  {
   COMPLEXNUM A;
   A.real = this->num.real;     // Use current object's real number
   A.imag = this->num.imag;   // Use current object's imaginary number
   CmpRoot (&A);              // call FORTRAN subroutine
   return Complex (A.real, A.imag);  // Return complex object
  }

Complex operator+ (Complex A, Complex B)
  {
   Complex Temp;
   Temp.num.real = A.num.real + B.num.real;
   Temp.num.imag = A.num.imag + B.num.imag;
   return Temp;            // Return complex object
  }

void Complex::display() const
  {
   // This subroutine display the complex number in an (a, bi) format
   cout << "(" << num.real << ", " << num.imag << "i)";
  }

Complex::Complex (float r, float i)
  {
   num.real = r;           // Constructor with arguments:
   num.imag = i;           // Initialize each member in the COMPLEXNUM
  }                        // data structure

Complex::Complex ()
  {                        // Default constructor:
   num.real = 1.0F;        // Initialize real part to 1.0
   num.imag = 1.0F;        // Initialize imaginary part to 1.0
  }

void main ()
  {
   Complex Var1(3.0F, 5.0F),  // Call constructor with arguments
           Var2,                    // Call default constructor
           Result;                  // Call default constructor
   cout << "The object Var1 contains:   ";
   Var1.display ();           // Call member function display()
   cout << endl;
   cout << "The object Var2 contains:   ";
   Var2.display ();           // Call member function display()
   cout << endl;

   cout << "      Adding Var1 + Var1:   ";

   Result = Var1 + Var2;      // Use the overloaded + operator
                              // to add the objects
   Result.display ();         // Call member function display()
   cout << endl << endl;

   cout << "The Square Root of the Complex Object Var1: ";
   Result = Var1.SqRoot ();   // Call member function SqRoot() to
                              // find the square root of the object
   Result.display ();         // Call member function display()
   cout << endl;
  }


Source Code 2

      SUBROUTINE CmpRoot (A)
      COMPLEX A
      A = SQRT(A)     ! Use the internal FORTRAN square
                      ! root function for complex numbers
      RETURN
      END

c Note: c FORTRAN's built-in type COMPLEX, can be represented in C/C++ c as a structure with two float data members. The first element c in the structure represents the real part, and the second c element represents the imaginary part.

Project Makefile

ALL : Sample.EXE

Sample.EXE : Sample.OBJ ForSub.OBJ

   Link Sample.OBJ ForSub.OBJ,, NUL, /NOD LLIBCE OldNames LLIBFERC;

Sample.OBJ : Sample.CPP
   CL /AL /c Sample.CPP

ForSub.OBJ : ForSub.FOR
   FL /AL /c ForSub.FOR


Additional reference words: kbinf 5.10 7.00
KBCategory: kbprg kbinterop kbcode
KBSubcategory: FORTLngIss CLngIss


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 17, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.