Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!
26729 Discussions

Passing Numeric SafeArray from VB.Net to FORTRAN

Bruce_Barker
Beginner
147 Views

Hello,

I'm trying to modify the Safearray example for passing multi-dimensional string arrays from VB.Net to Fortran. I want to be able to pass large REAL*8 arrays using Safearray. I have a program that exceeds the stack storage to due large array sizes and I want to pass them using Safearrays. I modified the example but I can't seem to get SafeArrayGetElement statement to retrieve values from the passed in array.  The code below shows the VB calling routine with the FORTRAN routine below. SafeArrayGetElement returns 0 for the array index provided. I intend to use a pointer to CurElem to get the value and work on it.

Any help would be appreciated.

Imports System.Runtime.InteropServices ' Required for using MarshalAs
Public Class Form1

    ' Declare the Fortran routine.  The name of the routine is case-sensitive
    ' and the path to the DLL is explicit.  When run from Visual Studio, the DLL
    ' is looked for in the BIN subfolder of the VB.NET project
    '
    ' By default, VB.NET would simply pass the data to the DLL without any bounds
    ' information (and no chance of rewriting the strings).  So we use the MarshalAs
    ' attribute to tell it to pass a SafeArray.  If you were passing numeric types,
    ' you could just pass the data and access it as a normal array.
    '
    Private Declare Sub ForCall Lib "SafeArrayFORTRAN.dll" _
     (<MarshalAs(UnmanagedType.SafeArray)> ByRef array1(,) As Double)

    Private myarray(2, 3) As Double
    Private Sub _cmdRun_Click(sender As Object, e As EventArgs) Handles _cmdRun.Click
        myarray(0, 0) = 12
        myarray(0, 1) = 11
        myarray(0, 2) = 10
        myarray(0, 3) = 9
        myarray(1, 0) = 8
        myarray(1, 1) = 7
        myarray(1, 2) = 6
        myarray(1, 3) = 5
        myarray(2, 0) = 4
        myarray(2, 1) = 3
        myarray(2, 2) = 2
        myarray(2, 3) = 1

        Call ForCall(myarray)

    End Sub
End Class


      Subroutine ForCall(VBArray)
!DEC$ ATTRIBUTES DLLEXPORT,REFERENCE,STDCALL::ForCall
!DEC$ ATTRIBUTES ALIAS: 'ForCall'::ForCall
!DEC$ ATTRIBUTES REFERENCE :: VBArray
      use ifcom ! Declare SafeArray and BSTR interfaces

      implicit none
  
      integer(int_ptr_kind()), intent(inout) :: VBArray  !Pointer to a SafeArray structure  
      INTEGER(INT_PTR_KIND()) :: ptrElem
      REAL*8,TARGET :: CurElem
      POINTER(ptrElem, CurElem)  ! This says that ptrElem holds the address of CurElem.     

!> Array in which we will keep track of array bounds
      type bounds_type
        integer lb  ! Lower Bound
        integer ub  ! Upper Bound
      end type bounds_type
 !<    
      integer nbounds  ! Number of bounds
      type(bounds_type), allocatable :: bounds(:)
      integer, allocatable :: indexes(:)  ! Array to hold current element indexes
      
      integer :: i, j, iRes
      nbounds = SafeArrayGetDim (VBArray)
      allocate (bounds(nbounds), indexes(nbounds))
      
      do i=1,nbounds
        ires = SafeArrayGetLbound (VBArray, i, bounds(i)%lb)
        ires = SafeArrayGetUbound (VBArray, i, bounds(i)%ub)
      end do
      
      DO j=bounds(1)%lb,bounds(1)%ub 
        DO i=bounds(2)%lb,bounds(2)%ub
          indexes(1)=i+1
          indexes(2)=j+1
          ires = SafeArrayGetElement (VBArray, indexes(1), loc(ptrElem))
          !OUTPUT CurElem HERE
        end do
      end do
      deallocate (bounds)
      deallocate (indexes)
  
      return  
      end subroutine ForCall

 

0 Kudos
3 Replies
Bruce_Barker
Beginner
147 Views

Also, is there a comprehensive reference on calling SafeArrays from Intel Fortran. i couldn't find much in the way of documentation on the topic.

Thanks!

Bruce_Barker
Beginner
147 Views

Ok, I found the solution to my original problem, which was a Stack Overflow Exception when passing large arrays to my FORTRAN dll. I was trying to correct the issue by passing SafeArrays. A much simpler approach is to change the Heap Array parameter to 0. The answer came from here: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/279050

 

Kevin_D_Intel
Employee
147 Views

Glad you found a solution. Thank you for sharing your findings/solution also.

Reply