» Sign in
  

Description

 

The following is an example of calling a Microsoft® Visual C/C++ routine from Visual Fortran. Comments in the source show what changes are necessary to have the Visual C/C++ code in a DLL or to have the C++ routine in a C++ "class". The instructions below assume you have Visual Fortran and Microsoft Visual C/C++ 5.0 or later installed and sharing the Developer Studio environment (requires the same major release of Visual Fortran and Visual C/++, for example V5 of both or V6 of both.)

  1. Create a "Fortran Console Application" (V6) or "Win32 Console Application" (V5) project for the main program, call it "VF Calls VC". If using V6, select "empty project" in the project wizard.
  2. In this project, create a C/C++ source file called "c_routine" (leave the file type off - it will default to .cpp) with the following code:
    /* C routine called by Fortran main program ** ** Converts integer input argument to text, appends ** the text to string input argument and stores the ** result in the string output argument */ #include <stdio.h> /* If the file type for this source is .cpp, and you want ** to put the routine in a class, comment out the following ** line which disables C++ name mangling. You will then ** have to use DUMPBIN /SYMBOLS xxx.obj to determine the ** correct "mangled" external name to use in a Fortran ** !DEC$ ATTRIBUTES ALIAS:'xxx' directive. If the file ** type is .c, remove the following line */ extern "C" /* If you want this routine to be in a DLL, uncomment the ** following line */ // __declspec(dllexport) void c_routine ( int int_arg, char* input_text, char* output_text ) { sprintf(output_text,"%s%i ",input_text,int_arg); } 
  3. In this project, create the following Fortran Free-form source file - call it "fmain" (the file type will default to .f90):
    PROGRAM fmain IMPLICIT NONE ! This is an example of a Fortran main program calling ! a C routine. Commented out text shows how to call the ! C routine in a DLL and how to call it if it is in C++ ! ! Declare the interface for the C routine we'll call ! INTERFACE SUBROUTINE c_routine (int_arg, str_in, str_out) ! ! Tell Fortran that this is a C routine we are ! calling. This establishes default naming and ! argument passing conventions !DEC$ ATTRIBUTES C :: c_routine ! If we wanted c_routine to be accessed from a DLL, ! we'd add the "DLLIMPORT" attribute, like so: (remove one ! of the leading "!" characters to enable): !!DEC$ ATTRIBUTES DLLIMPORT :: c_routine ! If we wanted the C routine to be in C++ (a .cpp file ! type and NOT have the 'extern "C"' attribute, we need ! to specify the proper C++ name-mangled alias. Do this ! from a command prompt with DUMPBIN /SYMBOLS xxx.obj ! In the case of our routine, the directive looks like the following ! (remove one of the leading "!" characters to enable): !!DEC$ ATTRIBUTES ALIAS:'®c_routine@@YAXHPAD0@Z' :: c_routine INTEGER int_arg CHARACTER*(*) str_in,str_out ! ! Specify that the CHARACTER arguments are by reference ! with no hidden length !DEC$ ATTRIBUTES REFERENCE :: str_in, str_out END SUBROUTINE c_routine END INTERFACE CHARACTER*80 OUTPUT_TEXT INTEGER IN_ARG, OUTPUT_LEN CHARACTER*80 INPUT_TEXT INPUT_TEXT = "Testing..."C ! C suffix adds a null terminator IN_ARG = 123 ! Call c_routine. It will return text in OUTPUT_TEXT ! CALL c_routine (in_arg, input_text, output_text) ! Find the length of the output text, looking ! for the trailing blank ! OUTPUT_LEN = INDEX(OUTPUT_TEXT," ") IF (OUTPUT_LEN == 0) OUTPUT_LEN = 80 ! Write the string to the console ! WRITE (*,*) OUTPUT_TEXT(1:OUTPUT_LEN) END 
  4. Click on Build. If you get a linker error about LIBCD causing a conflict, select Project..Settings..C/C++..Code Generation and set Use Run-Time Library to Single-Threaded.
  5. Run the application. it should display "Testing...123" in the console window.

To build the C/C++ code into a DLL, create a separate DLL project for the C routine. Uncomment the __declspec(dllimport) directive and build the DLL. In the Fortran project, uncomment the !DEC$ ATTRIBUTES DLLIMPORT directive (remember that the !DEC$ string must remain), add the DLL's .LIB to your project, and build. To run the program, make sure that the DLL is either in the same directory as the .EXE or somewhere on your PATH.

» Back to Examples

 



Manage My AllianceOne Membership

 
 » Sign in
 » Join AllianceOne
 » Contact us