View Full Version : Passing multi-dimensioned arrays
kturok
08-20-2003, 03:59 PM
I have legacy code that I have successfully compiled into Fortran.Net. The output parameters of a particular subroutine are multidimensional arrays of Doubles. When I access the dll containing the aforementioned subroutine from VB.Net, however, the method signature is confusing. It expects a single dimension array of Doubles. Can I not pass multi-dimensioned arrays between Fortran.Net and VB.Net? I tested the CTS, and it is possible to pass them between VB and C#. Back to the problem - When I try to declare one of the arrays that I have to supply to the Fortran subroutine as Dim x() as Double, the Fortran subroutine throws a null reference exception. When I declare it as Dim x(1000) as Double, the Fortran subroutine executes, but it does not return the correct values because I am missing several dimensions. Finally, when I declare my array as Dim x(90, 4, 4) which is the exact specification in my Fortran code, the VB compiler throws an error telling me that a 3 dimensional array of double cannot represent a 1 dimensional array of double.
When viewed in the object browser, every parameter of my Fortran.Net subroutine is opposite of what I expected. Example - all values needed for input are by reference and all output parameters are by value. If my output arrays are not passed by reference, how will I get a reference to them in my VB code?
Frustrated in SC,
Kim
tzeis
08-21-2003, 05:08 PM
The problem that you are experiencing is caused by a fundemental difference in how Fortran implements multiple dimension arrays as opposed to how the .NET Framework implements them.
The Fortran standard explicitly defines the order that an array element will appear in memory. The gist of this requirement is that the leftmost array index will change the fastest as you sequentially step through memory. The .NET Framework uses the "C" convention for multiple dimension arrays, in which the rightmost array element changes the fastest. Because of this conflict, Fortran for .NET implements all arrays with a singly dimensioned array object, and preserves the Fortran array ordering requirements. Internally, multiple dimension Fortran arrays conform to the Fortran standard, but externally, they all appear as single dimension array objects.
To relate the position of an element of the single dimension array object to a 3 dimensional array subscripts as used in Fortran, use the following formula: for an array with dimensions (d1,d2,d3), the array element (s1,s2,s3) will appear in the position s1+(s2*d1)+(s3*d1*d2)
To convert from the single dimension to a multi dimension Framework array, it looks like the brute force method is the only one available. The procedure would be to pack the values of the multiple dimension Framework array in to a single dimension array according to the formula, pass the single dimension array to the Fortran subprogram and unpack the results upon return.
I have included a zip showing how the pack and unpack routines might look for the case a 3 dimensional integer array. These routines are called before and after calling the Fortran code, there are no changes needed to the Fortran code. I think that a more general conversion utility would be useful.
All that being the case, I think that you also have the option of writing the front end using Fortran for .NET. You pretty much have the same design tools available for Fortran as for VB.NET, but when using the Fortran designers, the array sequencing problem is not present. I realize that due to previous investments in writing the front end in VB this suggestion might not be practical.
kturok
08-21-2003, 05:42 PM
Thank you for the fantastic response! It makes perfect sense now, and the code you sent illustrated the concept perfectly. I'm just tackling piles of legacy Fortran code for the first time, and I really appreciate your taking the time to answer my question.
Kind Regards,
Kim
vBulletin® v3.6.8, Copyright ©2000-2010, Jelsoft Enterprises Ltd.