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