- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have been developing a VB .NET program in VisualStudio environment for some years, which manipulates an Intel Fortran IFX DLL. Until version IFX 2023.2, all programs presented correct results and were verified in debug mode both in VB and in Fortran. However, I recently updated the IFX compiler to version 2024.0 and now the results are being incorrectly presented. After some tests, I observed that the passing of individual variable results is wrong, which does not occur when the results are vectors. The following source codes illustrate the problem.
[VB Code]
Public Class Form1
'Public Declare Auto Sub ProcessArray Lib "TesteArrayFortran.dll" (
' ByRef n As Integer,
' <MarshalAs(UnmanagedType.LPArray)> arr As Double(),
' <MarshalAs(UnmanagedType.LPArray)> sai As Double(),
' <MarshalAs(UnmanagedType.LPArray)> sum1 As Double,
' <MarshalAs(UnmanagedType.LPArray)> sum2 As Double())
Public Declare Auto Sub ProcessArray Lib "TesteArrayFortran.dll" (
ByRef n As Integer,
arr As Double(), sai As Double(),
sum1 As Double, sum2 As Double())
Private Sub Button1_Click(
sender As Object, e As EventArgs
) Handles Button1.Click
Dim sum1 As Double
Dim sum2(0) As Double
Dim arr() As Double = {1.0, 2.0, 3.0, 4.0, 5.0}
Dim n As Integer = arr.Length
Dim sai(4) As Double
ProcessArray(n, arr, sai, sum1, sum2)
Console.WriteLine($"n = {n}")
Console.WriteLine($"sai(0) = {sai(0)}")
Console.WriteLine($"sai(1) = {sai(1)}")
Console.WriteLine($"sai(2) = {sai(3)}")
Console.WriteLine($"sai(3) = {sai(3)}")
Console.WriteLine($"sai(4) = {sai(4)}")
Console.WriteLine($"sum1 = {sum1}")
Console.WriteLine($"sum2 = {sum2(0)}")
End Sub
End Class
[Fortran Code]
SUBROUTINE ProcessArray(n, entra, sai, sum1, sum2)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'ProcessArray' :: ProcessArray
!DEC$ ATTRIBUTES REFERENCE :: n
IMPLICIT NONE
EXTERNAL :: Check
INTEGER, INTENT(IN) :: n
REAL*8, INTENT(IN) :: entra(n)
REAL*8, INTENT(OUT) :: sai(n), sum1, sum2(1)
INTEGER :: i
DO i = 1, n
sai(i) = entra(i) * entra(i)
END DO
CALL Check(n, entra, sum1, sum2)
END SUBROUTINE ProcessArray
SUBROUTINE Check(n, entra, sum1, sum2)
IMPLICIT NONE
INTEGER,INTENT(IN) :: n
REAL*8,INTENT(IN) :: entra(n)
REAL*8,INTENT(OUT) :: sum1, sum2(1)
INTEGER :: i
sum1 = 0
DO i = 1, n
sum1 = sum1 + entra(i)
END DO
sum2(1) = sum1
RETURN
ENDSUBROUTINE Check
I believe the error is related to some configuration of IFX 2024.0 which did not exist or had a different behavior until IFX 2023.2. Is it possible to analyze the issue and suggest some configuration that corrects the problem?
Some additional comments:
1) Is it necessary to use the command <MarshalAs(UnmanagedType.LPArray)>? In my tests, there is no difference at all between using it or not when IFX is configured with the STDCALL calling convention (/iface:stdcall).
2) Partial results are only correct when IFX is configured with a) Initialize Variables to Signaling NaN = Yes (/Qinit:snan); b) Initialize Variables to Zero = Yes (/Qinit:zero); c) Initialize Arrays as well as Scalars = Yes (/Qinit:arrays).
3) In my example, the elements of the "sai" array coincide with the elements of the "arr" array. The sum of these elements is 1+2+3+4+5=15, which should be correctly reported by the first element of the "sum2" array (sum2(0) = 15). However, the variable "sum1" is calculated in the same way but results incorrectly in sum1 = 0.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would like to inform you that: a) my code is 64-bit; b) it is not necessary to use the attribute <MarshalAs(UnmanagedType.LPArray)>; c) after days of researching and combining instructions and settings in VB .NET and Fortran IFX, I managed to find the solution to my problem. Basically, the variable I want to pass between Fortran subroutines ('sum', in this case) must have the ByRef attribute on both the Fortran and VB sides to be presented to the user. The configuration of the IFX compiler should be: Calling Convention = STDCALL, REFERENCE (/iface:stdref).
In case it is helpful for anyone else, I am sharing the code snippets of my new test, leaving out only the important additional parts, as well as the output of the results.
***** VB .NET Code
Imports System.Diagnostics.Debug
Imports System.Runtime.InteropServices
Imports System.Environment
Public Class Form1
<DllImport("TesteArrayFortran.dll")>
Public Shared Sub ProcessArray(
ByRef n As Integer,
ByRef soma As Double,
arr As Double())
End Sub
Private Sub Button1_Click(
sender As Object, e As EventArgs
) Handles Button1.Click
Dim soma As Double
Dim arr() As Double = {1.1, 2.1, 3.1, 4.1, 5.1}
Dim n As Integer = arr.Length
ProcessArray(n, soma, arr)
WriteLine($"{NewLine}")
WriteLine($"***** {Now}")
For i = 0 To 4
WriteLine($"arr({i}) = {arr(i):#0.0}")
Next i
WriteLine($"soma = {soma:#0.0}")
End Sub
End Class
***** Fortran Code
SUBROUTINE ProcessArray(n, sum, entra)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'ProcessArray' :: ProcessArray
!DEC$ ATTRIBUTES REFERENCE :: n, sum
IMPLICIT NONE
INTEGER, INTENT(IN) :: n
REAL*8, INTENT(INOUT) :: sum
REAL*8, INTENT(IN) :: entra(n)
INTERFACE
SUBROUTINE Check(n, sum, entra)
IMPORT
INTEGER, INTENT(IN) :: n
REAL*8, INTENT(INOUT) :: sum
REAL*8, INTENT(IN) :: entra(n)
END SUBROUTINE Check
END INTERFACE
CALL Check(n, sum, entra)
END SUBROUTINE ProcessArray
SUBROUTINE Check(n, sum, entra)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n
REAL*8, INTENT(INOUT) :: sum
REAL*8, INTENT(IN) :: entra(n)
INTEGER :: i
sum = 0
DO i = 1, n
sum = sum + entra(i)
END DO
END SUBROUTINE Check
***** Output Results
***** 06/03/2024 18:07:29
arr(0) = 1,1
arr(1) = 2,1
arr(2) = 3,1
arr(3) = 4,1
arr(4) = 5,1
soma = 15,5
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page