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

can't get value correctly from fortran dll to VB.net back

Lu_Zhang
Beginner
469 Views

Hi Everyone,
I can't make the following code working in VS2015 with IVF, though it is very simple. Value C from dll is always 0, not 6.0 as expected. Thanks so much.
//my VB code:
Public Class Form1
    Public Declare Sub DLL_ROUT Lib "D:\Debug\Dll2.dll" _
    (ByVal A As Double, ByVal B As Double, ByVal C As Double)
    Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim A As Double
        Dim B As Double
        Dim C As Double
        A = 2.0
        B = 3.0
        Call DLL_ROUT(A, B, C)
        Button1.Text = C
    End Sub
End Class
 
// my Fortran  dll code:
SUBROUTINE DLL_ROUT (A, B, C)
IMPLICIT NONE
! Specify that DLL_ROUT is exported to a DLL
! and that the external name is 'DLL_ROUT'
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL :: DLL_ROUT
!DEC$ ATTRIBUTES ALIAS:'DLL_ROUT' :: DLL_ROUT
DOUBLE PRECISION A, B, C
C = A * B
RETURN
END

0 Kudos
9 Replies
FortranFan
Honored Contributor II
469 Views

I suggest the following instead based on P/Invoke in .NET and C interoperability in Fortran:

   <DllImport("D:\Debug\Dll2.dll", CallingConvention:=CallingConvention.Cdecl)> _
   Public Shared Sub DLL_ROUT (A As Double, B As Double, ByRef C As Double)
   subroutine DLL_ROUT(A, B, C) bind(C, name="DLL_ROUT")
   !DEC$ ATTRIBUTES DLLEXPORT::DLL_ROUT

      use, intrinsic :: iso_c_binding, only : c_double

      !.. Argument list
      real(c_double), intent(in), value :: A
      real(c_double), intent(in), value :: B
      real(c_double), intent(inout)     :: C

      C = A * B

      return

   end subroutine DLL_ROUT

 

0 Kudos
Steve_Lionel
Honored Contributor III
469 Views

I'm not sure if FortranFan's suggestion will work, but the reason your initial version doesn't work is that just saying STDCALL changes the arguments to pass-by-value, which makes it impossible to return anything. Add to the Fortran:

!DEC$ ATTRIBUTES REFERENCE :: C

This will match the ByRef in the VB.

0 Kudos
Lu_Zhang
Beginner
469 Views

It works, amazing! Thanks FortranFan!

0 Kudos
Lu_Zhang
Beginner
469 Views

This is awesome, Thanks Steve!

0 Kudos
Lu_Zhang
Beginner
469 Views

Both work very well. Thank you guys!

0 Kudos
FortranFan
Honored Contributor II
469 Views

Steve Lionel (Ret.) wrote:

I'm not sure if FortranFan's suggestion will work, ..

Huh?  It's been only >3.5 years here where readers have been guided to consider the better option with Microsoft .NET code to interoperate with Fortran is to employ P/Invoke: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/594478

Fdll.f90

module m

   use, intrinsic :: iso_c_binding, only : c_double

   implicit none

contains

   subroutine DLL_ROUT(A, B, C) bind(C, name="DLL_ROUT")
   !DEC$ ATTRIBUTES DLLEXPORT::DLL_ROUT

      !.. Argument list
      real(c_double), intent(in), value :: A
      real(c_double), intent(in), value :: B
      real(c_double), intent(inout)     :: C

      C = A * B

      return

   end subroutine DLL_ROUT

end module m

Test.vb file

Imports System.IO
Imports System.Text
Imports System.Runtime.InteropServices

Namespace Fortran

   Public Class Fdll

      <DllImport("c:\Debug\Fdll.dll", CallingConvention:=CallingConvention.Cdecl)> _
      Public Shared Sub DLL_ROUT (A As Double, B As Double, ByRef C As Double)
      end Sub

   End Class

   NotInheritable Class Test

      Private Sub New()
      End Sub

      Public Shared Sub Main()

         Dim a As Double
         Dim b as Double
         Dim c as Double

         ' Write header
         Console.WriteLine("*** Test Fortran Interop using VB ***" + vbLf)

         Try

            a = 2.0
            b = 3.0
            c = 0.0
            Fdll.DLL_ROUT(a, b, c)

            Console.WriteLine("c = " + c.ToString("###0.0#"))

         Catch ex As Exception

            Console.WriteLine(ex.Message)

         Finally

            Console.WriteLine("Press any key to continue..")
            Console.ReadKey()

         End Try

      End Sub

   End Class

End Namespace
C:\Debug>ifort /dll /libs:static fdll.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 19.0.3.203 Build 20190206
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.16.27027.1
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:fdll.dll
-dll
-implib:fdll.lib
fdll.obj
   Creating library fdll.lib and object fdll.exp

C:\Debug>vbc -platform:x86 test.vb
Microsoft (R) Visual Basic Compiler version 2.10.0.0 (b9fb1610)
Copyright (C) Microsoft Corporation. All rights reserved.


C:\Debug>test.exe
*** Test Fortran Interop using VB ***

c = 6.0
Press any key to continue..

C:\Debug>
C:\Debug>ifort /dll /libs:static Fdll.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.3.203 Build 20190206
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.16.27027.1
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:Fdll.dll
-dll
-implib:Fdll.lib
Fdll.obj
   Creating library Fdll.lib and object Fdll.exp

C:\Debug>vbc -platform:x64 test.vb
Microsoft (R) Visual Basic Compiler version 2.10.0.0 (b9fb1610)
Copyright (C) Microsoft Corporation. All rights reserved.


C:\Debug>test.exe
*** Test Fortran Interop using VB ***

c = 6.0
Press any key to continue..

C:\Debug>

 

0 Kudos
Steve_Lionel
Honored Contributor III
469 Views

When I said "I'm not sure" I meant that literally - I thought it might, but am not familiar with the angle bracket syntax for use in VB code, so I didn't know. I didn't say it wouldn't work. But I knew my suggestion would work and was a smaller change.

0 Kudos
FortranFan
Honored Contributor II
469 Views

Lu Zhang wrote:

It works, amazing! Thanks FortranFan!

Please see this thread from about 5 years ago, especially Quote #2 where I suggest moving away from VB6/COM based approaches with STDCALL, etc. from the bygone 1990s when it comes to working with .NET technologies:

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/509148

0 Kudos
Lu_Zhang
Beginner
469 Views

Thank you so much, FortranFan.

0 Kudos
Reply