Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29267 Discussions

Calling Fortran Function in static library from C++ in Visual Studio 2008

proud2bhaole
Beginner
2,498 Views
Hi,

I have a program that is mostly visual C++ but also calls some Fortran functions.

I have the source code (*.f90 files) for the fortran functions and would like to call them from the .cpp files.

How do i do this?

Should I create a static library that contains the fortran code? if so, how do I call the function using C++?

Or

is there an easier way (in visual Studio 2008)
0 Kudos
1 Solution
Steven_L_Intel1
Employee
2,498 Views
Remove the __stdcall. You seem to be working with code from Microsoft Fortran PowerStation, which used STDCALL. Intel Visual Fortran does not.

View solution in original post

0 Kudos
6 Replies
Steven_L_Intel1
Employee
2,498 Views
  1. Create a Fortran Static Library project for your Fortran code in the same solution as the VC++ project
  2. Change the Fortran project setting Libraries > Disable default library search rules to "No"
  3. Right click on the VC++ project, select Dependencies. Check the box for the Fortran project
  4. Follow the instructions here to configure Visual C++ to link to Fortran
  5. In the C++ code, use 'extern "C"' when declaring the Fortran functions. By default, Fortran names are uppercase.
For more information, see the Fortran documentation section on mixed-language applications.
0 Kudos
proud2bhaole
Beginner
2,498 Views
Hi Steve

Thanks for the answer.

Here's one of the .f90 files that i have to work with (below).

And in the VC++ code i've declared it like so:

extern "C"
{
void __stdcall DISTORTION(int, int, double, int, int, int*, int*, int*, double&, int, double*, double*);
void __stdcall SCALE_FACTOR(int, int, float, int*, int*, double&);
}

But i still get the following error: 'LNK2019: unresolved external symbol _SCALE_FACTOR@24..'

Any idea what I'm doing wrong? I've set the settings just like how you said.

Thanks!
Kevin


[cpp]	 SUBROUTINE SCALE_FACTOR(HLINES, VLINES, SPACE, GRIDY, GRIDX, SCALE)
!*************************************************************
!     Calculate the scale factor
!*************************************************************
!     Calculate the scale for each side of the rectangle of digitized grid points
!     Remember that coords from digitize are X down Y across
!     Points are 1=Top Left;2=Top Right;3=Bottom Left;4=Bottom Right
!     Lengths are: 1=top;2=bottom;3=left;4=right;5=diagonal;6=diagonal
!*************************************************************

	  !MS$ATTRIBUTES VALUE::HLINES
	  !MS$ATTRIBUTES VALUE::VLINES
  	  !MS$ATTRIBUTES VALUE::SPACE
	  !MS$ATTRIBUTES REFERENCE::SCALE

	! INTEGER*4 == int
	! REAL*4    == float
	! REAL*8    == double

	  INTEGER(4) HLINES, VLINES                 
	  REAL(4)    SPACE                                 
	  INTEGER(4) GRIDY(0:6), GRIDX(0:6)                
	  REAL(8)    SCALE, DEV                                 
      DIMENSION  SQUARES(6), LENGTH(6), SIDESCAL(6)
!*****************************************************************!
! THE FRAME IN FORTRAN IN DIFFERENT FROM WHAT IN C

      LENGTH(1)=SQRT((GRIDX(0)-GRIDX(1))**2.+(GRIDY(0)-GRIDY(1))**2.)
      LENGTH(2)=SQRT((GRIDX(2)-GRIDX(3))**2.+(GRIDY(2)-GRIDY(3))**2.)
      LENGTH(3)=SQRT((GRIDX(0)-GRIDX(2))**2.+(GRIDY(0)-GRIDY(2))**2.)
      LENGTH(4)=SQRT((GRIDX(3)-GRIDX(1))**2.+(GRIDY(3)-GRIDY(1))**2.)
      LENGTH(5)=SQRT((GRIDX(0)-GRIDX(3))**2.+(GRIDY(0)-GRIDY(3))**2.)
      LENGTH(6)=SQRT((GRIDX(2)-GRIDX(1))**2.+(GRIDY(2)-GRIDY(1))**2.)
!*************************************************************
!     Compare each pair to make sure they differ by no more than 2 pixels
!     ("pair" means top-bottom; left-right; diagonal-diagonal)
!*************************************************************
     DO I=1,5,2
        IF (ABS(LENGTH(I)-LENGTH(I+1)) .GE. 2.) THEN
          !PRINT *, '!!! ERROR !!! Difference > 2 pixels in grid'
		  !STOP
		  SCALE=-3
		  RETURN          
        ENDIF
	 END DO
      
      SQUARES(1)=(VLINES-1)
      SQUARES(2)=SQUARES(1)
      SQUARES(3)=(HLINES-1)
      SQUARES(4)=SQUARES(3)
      SQUARES(5)=SQRT((VLINES-1)**2.+(HLINES-1)**2.)
      SQUARES(6)=SQUARES(5)

	  SCALE=0.

      DO I=1,6
        SIDESCAL(I)=SPACE*SQUARES(I)/LENGTH(I)
        SCALE=SCALE+SIDESCAL(I)/6.
	  END DO

!*************************************************************
!     Allow only 1% variation in calculated scales
!*************************************************************
!      DO I=1,6
!        DEV=SIDESCAL(I)/SCALE
!        IF (DEV .GT. 1.01 .OR. DEV .LT. 0.99) THEN
!          PRINT *, '!!! ERROR !!! >1% variation in scales'
!          STOP
!        ENDIF
!	  END DO

	 END SUBROUTINE SCALE_FACTOR
[/cpp]

0 Kudos
Steven_L_Intel1
Employee
2,499 Views
Remove the __stdcall. You seem to be working with code from Microsoft Fortran PowerStation, which used STDCALL. Intel Visual Fortran does not.
0 Kudos
TimP
Honored Contributor III
2,498 Views
While a degree of stdcall compatibility is available as an option for 32-bit ifort, it isn't the default or the recommended choice. Unless you specify differently, or if you use 64-bit compilers, cdecl is the default, and the required mode, whether you use iso_c_binding, or an ifort legacy interface.
0 Kudos
proud2bhaole
Beginner
2,498 Views
Hi Steve

Is the fortran documentaion you speak of found in the "Intel Visual Fortran Compiler User and Ref Guides"?

Thanks, taking the '__stdcall' out worked great!!!

Kevin
0 Kudos
Steven_L_Intel1
Employee
2,498 Views
Kevin, yes, it's in the "Building Applications" volume. You might also look at the provided "MixedLanguage" samples which contain two that mix Fortran and C/C++.
0 Kudos
Reply