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

Use Fortran dll in VC++

yan__san-chi
Beginner
515 Views

Hi! I created a Fortran code with 3 function.  This is my Fortran code:

real function circle_area(radius)
!DEC$ ATTRIBUTES DLLEXPORT :: CIRCLE_AREA
!DEC$ ATTRIBUTES ALIAS : "Circle_Area" :: CIRCLE_AREA
    
        implicit none
       real radius
       real, parameter :: PI = 3.14159
        circle_area = radius*radius*PI
       return

end function

integer function sum(a)
!DEC$ ATTRIBUTES DLLEXPORT :: SUM

     implicit none
     integer :: a(10)
      integer i
      sum=0
     do i=1,10
      sum=sum+a(i)
     end do
      return

end function

subroutine MakeLower(string)
!DEC$ ATTRIBUTES DLLEXPORT :: MAKELOWER

      implicit none
      character(len=*) :: string
      integer :: len, i, code
      len = len_trim(string)
      do i=1,len
        code = ichar(string(i:i))
        if ( code >= ichar('a') .and. code <= ichar('z') ) then
          string(i:i) = char(code-32)
        end if
      end do
      return

end subroutine

 I use this Fortran code to create dll (Dll1). Then I wrote a c program to call function  circle_area() in Fortran code.

#include "stdafx.h"
#include "stdlib.h"
extern "C" {float circle_area(float *a); }

int _tmain(int argc, _TCHAR* argv[])
{
    float b = 3.;
    circle_area(&b);
    system("pause");
    return 0;
}

Before I ran my c code, I included my dll in Visual Studio 2013. First I added my Dll1.lib directory in VC++ directories-> Library Directories,  in Linker -> General -> Additional Library Directories  added Dll1.lib directory again,  in Linker -> Input -> Additional Dependencies added Dll1.lib. Last, I put Dll1.dll in c project folder that it will create .exe together. 

After running my c code, I got these messages :

error LNK2019: unresolved external symbol '_circle_area ' referenced in function '_wmain'

error LNK1120: 1 unresolved external symbol

It seems that I need  something setup. Can someone help me? 

0 Kudos
1 Solution
FortranFan
Honored Contributor II
515 Views

You may also want to keep in mind the standard option:

module m

   use, intrinsic :: iso_c_binding, only : c_float

   implicit none

   private

   public :: circle_area

   real(c_float), parameter :: PI = 3.14159 !.. Is this precise enough for your needs?
                                            !   pi = acos(-1.0_xx) is one way to get most precision 
                                            !   for a selected real kind of xx 

contains

   function circle_area(radius) result( Area ) bind(C, name="Circle_Area")
   !DEC$ ATTRIBUTES DLLEXPORT :: CIRCLE_AREA

      real(c_float), intent(in), value :: radius
      !.. Function result
      real(c_float) :: Area

      Area = PI*radius*radius

      return

   end function circle_area

end module m
#include <iostream>
using namespace std;

extern "C" {

   // Prototype for the Fortran Function
   float Circle_Area( float );

}

int main()
{

   float r = 2.0;

   cout << "Area of circle with radius of 2.0 = " << Circle_Area(r) << endl;

   return 0;

}

 

View solution in original post

0 Kudos
8 Replies
Steven_L_Intel1
Employee
515 Views

Add "DECORATE," before ALIAS. You told Fortran that the external name was just "Circle_Area" but C, on 32-bit WIndows, adds a leading underscore (as does Fortran for normal use.) DECORATE tells Fortran to add the appropriate platform-specific name decoration.

You don't put dll.lib in "Additional library directories". Instead you put the directory where dll.lib is put. Note also that you will need to copy the DLL itself to the executable directory.

0 Kudos
FortranFan
Honored Contributor II
516 Views

You may also want to keep in mind the standard option:

module m

   use, intrinsic :: iso_c_binding, only : c_float

   implicit none

   private

   public :: circle_area

   real(c_float), parameter :: PI = 3.14159 !.. Is this precise enough for your needs?
                                            !   pi = acos(-1.0_xx) is one way to get most precision 
                                            !   for a selected real kind of xx 

contains

   function circle_area(radius) result( Area ) bind(C, name="Circle_Area")
   !DEC$ ATTRIBUTES DLLEXPORT :: CIRCLE_AREA

      real(c_float), intent(in), value :: radius
      !.. Function result
      real(c_float) :: Area

      Area = PI*radius*radius

      return

   end function circle_area

end module m
#include <iostream>
using namespace std;

extern "C" {

   // Prototype for the Fortran Function
   float Circle_Area( float );

}

int main()
{

   float r = 2.0;

   cout << "Area of circle with radius of 2.0 = " << Circle_Area(r) << endl;

   return 0;

}

 

0 Kudos
yan__san-chi
Beginner
515 Views

Steve Lionel (Intel) wrote:

Add "DECORATE," before ALIAS. You told Fortran that the external name was just "Circle_Area" but C, on 32-bit WIndows, adds a leading underscore (as does Fortran for normal use.) DECORATE tells Fortran to add the appropriate platform-specific name decoration.

You don't put dll.lib in "Additional library directories". Instead you put the directory where dll.lib is put. Note also that you will need to copy the DLL itself to the executable directory.

"You don't put dll.lib in "Additional library directories".", I don't understand! Don't I add Dll1.lib directory in "Additional library directories"?

Does "copy the DLL" means copy the Dll1.dll only? 

0 Kudos
Steven_L_Intel1
Employee
515 Views

You put the directory containing dll1.lib there, not "dll1.lib".

Yes, copy the .dll only.

0 Kudos
yan__san-chi
Beginner
515 Views

Thanks for your help! I referenced you comments,then adjusted my code!

I am so happy that my program works now! But I have a big Fortran function called in C++.

So I need to adjust Fortran function simply.

And is there any document or what I can read about using C++ call Fortran dll ?

 

#include "stdafx.h"
#include <iostream>
using namespace std;
extern "C" {float CIRCLE_AREA(float *a ); }

int _tmain(int argc, _TCHAR* argv[])
{

	float r = 2.;
	cout << "Area of circle with radius of 2.0 = " << CIRCLE_AREA(&r) << endl;
	system("pause");
	return 0;

}

 

0 Kudos
mecej4
Honored Contributor III
515 Views

There is a full chapter, "Mixed Language Programming", in the Intel Fortran Compiler Reference.

You may not find much about calling Fortran directly in C++. The Fortran standard specifies interoperability with C, not with C++. However, the extern "C" {...} construct of C++ takes care of this.

[Corrected by adding quotes, as stated in #8]

0 Kudos
Steven_L_Intel1
Employee
515 Views

That's: 

extern "C"

You need the quotes.

0 Kudos
yan__san-chi
Beginner
515 Views

Okay! I see. Thanks! 

0 Kudos
Reply