Visual Basic passing array to Fortran DLL in x64


Problem

A mixed VB/IVF project in which VB passed an array to Fortran DLL worked when built in ia32 configuration but fails when built with x64 configuration.


Environment

Windows x64, Visual Studio 2005 or 2008 with VB component and IVF component installed.  x64 project configurations.


Root Cause

Many VB users have been passing the first element of the array ByRef with the follow syntax:

Module Module1
Private Declare Sub FortranDLL Lib "SampleFortranDLL.dll" Alias "FORTRANDLL" (ByRef Array1 As Int32, ByRef Int32 As Int32)
Sub Main()
Try
Dim Test As Int32() = {1, 2, 3, 4, 5, 6}
FortranDLL(Test(0), Test.Length)

This works on ia32 but apparently just by luck.  This syntax is incorrect for x64.


Resolution

It seems VB handles array passing differently in x64 than Ia32. I would refer you to the following articles:

 

The interesting quote is from the MDSN article: “...snip...Arrays are layed out differently in managed code vs unmanaged code, so it was a total fluke that it worked simply be passing the first element ByRef anyway.”

The correct syntax for BOTH ia32 and x64 should follow this example:

Imports System.Runtime.InteropServices

Module Module1

Private Declare Sub FortranDLL Lib "FCALL.dll" Alias "FORTRANDLL" (<[In](), Out()> ByVal Array1() As Int32, ByRef Foo As Int32)

Sub Main()

Dim I As Int32

Try

Dim Test As Int32() = {1, 2, 3, 4, 5, 6}

FortranDLL(Test, Test.Length)

Console.WriteLine(" ")

Console.WriteLine("back in VB")

Console.WriteLine("Array elements after call return:")

For i = 0 To 5

Console.WriteLine(Test(i))

Next i

Catch ex As Exception

Console.WriteLine(ex.Message)

My.Computer.Clipboard.SetText(ex.Message)

Finally

Console.ReadKey()

End Try

End Sub

End Module

! FortranDLL

! Description: This sample demonstrates a mixed VB-Fortran

!              x64 application.  The purpose is to demonstrate

!              the VB declarations necessary to pass an array

!              from VB to IVF.

!              This is a Fortran subroutine contained in a 

!              DLL Project type and produces a DLL to be called

!              from Visual Basic.

! Input files:

!  NONE

! Output files:

!  NONE

! History:  v1.0

Subroutine FortranDLL( Array1, upbound )

!DEC$ ATTRIBUTES DLLEXPORT, ALIAS: 'FORTRANDLL' :: FortranDLL

!DEC$ ATTRIBUTES REFERENCE :: Array1

!DEC$ ATTRIBUTES REFERENCE :: upbound

Implicit None

! ...argument declarations

Integer(4) :: upbound

Integer(4) :: Array1(1:upbound)



! Local variables

Integer(4) :: I

write(*,'(A,I)') "Array upper bound passed in ", upbound

write(*,*) "Array elements passed in: "

do i=1,upbound

write(*,'("element:", I2, 2X, I8)' ) i, Array1(i)

end do

write(*,*) "Adding 10 to each element and passing back to VB"

Array1 = Array1 + 10



End Subroutine FortranDLL



 

附件尺寸
下载 vb-calls-fortranx64.zip215.73 KB
如需更全面地了解编译器优化,请参阅优化注意事项