Passing VB.NET Array to Fortran. Array will be not correctly read by F90

Passing VB.NET Array to Fortran. Array will be not correctly read by F90

Hi there,

since we´re planned to re-design our software at our company (whole programm was programmed in F90 with Fortran Compiler 11) we´re planned to to the GUI and easy operations through VB.NET.

The GUI building, event Handling and so, is much easier to code and to implement specific features.

But well ... Fortran is incredibly fast at mathematic operations, which our software is mainly developed for.
So plans are, to call F90 dll´s which are to do the mathematical stuff and send back the results to the VB.NET GUI.
Easy things like multiplie 2 integers, or square rooting, and so ... work like a charm and also strings working good (which are quite the hell on earth in F90 imho :D) ... but i am absolutely not  able to simply pass a 1-dimensional array to Fortran.

I tried it with a simple BubbleSort module, just to get the know-how and later be able to implement it to our software. Google does not helping me, and also the examples, which comes with the compiler does not help :(.

Here is the fortran module (sorry i have no idea how to set this in code tags ... the old forum had a function for that if i remeber correct ;) )

SUBROUTINE BubbleSortI4SingleArray(array)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, ALIAS : "BubbleSortI4SingleArray" :: BubbleSortI4SingleArray

implicit none
integer, intent(inOut) :: array(:)

integer :: temp
INTEGER :: i, j
LOGICAL :: swapped = .TRUE.

DO j = SIZE(array)-1, 1, -1
swapped = .FALSE.
DO i = 0, j
IF (array(i) > array(i+1)) THEN
temp = array(i)
array(i) = array(i+1)
array(i+1) = temp
swapped = .TRUE.
IF (.NOT. swapped) EXIT

END SUBROUTINE BubbleSortI4SingleArray

In VB.NET i tried 2 different Versions of implementing the Declare command ... at the 1st the array "redims" itself to only 1 number after running through the fortran dll.
At the 2nd, the array holds its size ... but not getting sorted. I also implemented a print *, size(array) in the fortran module, just to control, if the array is correctly "given" by VB.NET. Well ... a size of a few millions, only when it should have e.g. 10 shows me, that something between VB.NET to the Fortran module does not work correctly and fortran so cant sort the array.

Here are the 2 Declare methods i tried:
1)  Declare Sub BubbleSortI4SingleArray Lib "C:\sortdemo\sorts.dll" Alias "BubbleSortI4SingleArray" (ByRef array() As Integer)
2) Declare Sub BubbleSortI4SingleArray Lib "C:\sortdemo\sorts.dll" Alias "BubbleSortI4SingleArray" (<MarshalAs(UnmanagedType.SafeArray)> ByRef array() As Integer) 

Does anyone have an idea, what the hell i am doing wrong?
I also tried to give the size of the array by by using array.GetUpperBound(0) and "declare" it in fortran with array(0:upBound-1), since arrays in .NET are 0-based ... but that also won´t work :( 

Best regards, Oliver 

3 帖子 / 0 全新
Best Reply

Hi fellaz.

I tried in on my own for several hours. After changed to C#, were it is possible to work with pointers, i found a solution which works -> pointers

First I changed the DEC$ ATTRIBUTES at the fortran dll a bit.
I deleted the REFERENCE attribute and so the final code line is:
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, ALIAS : "BubbleSortI4SingleArray" :: BubbleSortI4SingleArray

Then i tried it in several ways in but nothing worked ... so i changed to  C#, since i already wrote a SSH wrapper for fortran a few years ago and so i knew, that there are pointers avaiable and they working.

So here is the delegate for the fortran DLL:
[DllImport("sorts.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "BubbleSortI4SingleArray")]
static extern void BubbleSortI4SingleArray(int* arrPtr, int bound);

Guess the code for the array filling and so is not nesscessarz so here are the important lines for calling the fortran dll (be sure to use an unsafe class and unsafe allowness to the compiler, or pointers wont work):
fixed (int* arrPtr = arrayx)
BubbleSortI4SingleArray(arrPtr, arrayx.GetUpperBound(0));

 Hope that this could help any other developer in the future :)

Best regards


Does it work when you explicitly pass the length of the array (declare the array as INTEGER, INTENT(INOUT) :: Array(lenOfArray))?

Its slightly less elegant, but if that works at least it gives you a stepping stone to investiage passing assumed shape arrays.