Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
24 Views

Use Fortran dll in VC++

Jump to solution

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

Accepted Solutions
Highlighted
Valued Contributor III
24 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
Highlighted
24 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.

Retired 12/31/2016
0 Kudos
Highlighted
Valued Contributor III
25 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
Highlighted
Beginner
24 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
Highlighted
24 Views

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

Yes, copy the .dll only.

Retired 12/31/2016
0 Kudos
Highlighted
Beginner
24 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
Highlighted
Black Belt
24 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
Highlighted
24 Views

That's: 

extern "C"

You need the quotes.

Retired 12/31/2016
0 Kudos
Highlighted
Beginner
24 Views

Okay! I see. Thanks! 

0 Kudos