Software Archive
Read-only legacy content
17061 Discussions

accessing an array via pointer returned from C++ routine

stober123
Beginner
419 Views
I am trying to get to the data in array that is created in a COM application. The interface routine specifies a return argument that is a pointer to a pointer to the data array. Is it even possible to access this data via FORTRAN?
Any ideas?
0 Kudos
4 Replies
Intel_C_Intel
Employee
419 Views
Yes it is possible. For best results post the IDL and optionally the C++ prototype. What f90 code did the Module Wizard produce for this routine? (I'd post that too)

-John
0 Kudos
stober123
Beginner
419 Views
I can supply the module wizard code, the C++ code is not mine, I'll have to look around for the IDL.
Wizard Code:
INTEGER*4 FUNCTION $IOPCGroup_SyncWrite($OBJECT, NumItems, ServerHandles, Values, Errors)
!DEC$ ATTRIBUTES DLLEXPORT :: $IOPCGroup_SyncWrite
IMPLICIT NONE

INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
INTEGER*4, INTENT(IN) :: NumItems
!DEC$ ATTRIBUTES REFERENCE :: NumItems
INTEGER(INT_PTR_KIND()), INTENT(IN) :: ServerHandles ! (SafeArray)
!DEC$ ATTRIBUTES REFERENCE :: ServerHandles
INTEGER(INT_PTR_KIND()), INTENT(IN) :: Values ! (SafeArray)
!DEC$ ATTRIBUTES REFERENCE :: Values
INTEGER(INT_PTR_KIND()), INTENT(OUT) :: Errors ! (SafeArray)
!DEC$ ATTRIBUTES REFERENCE :: Errors
INTEGER*4 $RETURN
INTEGER(INT_PTR_KIND()) $VTBL ! Interface Function Table
POINTER($VPTR, $VTBL)
$VPTR = $OBJECT ! Interface Function Table
$VPTR = $VTBL + 112 ! Add routine table offset
IOPCGroup_SyncWrite_PTR = $VTBL
$RETURN = IOPCGroup_SyncWrite($OBJECT, NumItems, ServerHandles, Values, Errors)
$IOPCGroup_SyncWrite = $RETURN
END FUNCTION $IOPCGroup_SyncWrite

I have tried this using the SAFEARRAY's, it works when run in the debugger, when run outside of the debugger it hangs in above write stmt. If I replace the Errors argument with a I*4 variable and ignore it (ie don't bother checking the values) everything is fine. This is possibly a memory corruption issue (the hang), but it is impossible to locate when everything runs fine in the debugger.
0 Kudos
Intel_C_Intel
Employee
419 Views
Errors is an explicit intent out safearray. So I'd bet that the COM method is allocating the memory for it (calling SafeArrayCreate) and passing it out - your description of what happens when you pass an int for Errors supports this too. You need to know this for certain. It is part of the semantic contract of the interface.

In your call to $IOPCGroup_SyncWrite you want ServerHandles and Values to be integer variables that hold pointers to SafeArrays that you have created and initialized. Errors should be an integer variable that you have initialized to some value (zero). On return, Errors should hold a valid pointer to a SafeArray that you could inspect if you'd like to.

If I am inferring properly from your posting, I'd do something like:
 
! ...  
 
real :: Errors(NumItems)  ! if Errors is of type real  
 
pointer (pErrors, Errors)  
 
integer :: psaOut  
 
! ...  
 
psaOut = 0  
 
hr = $IOPCGroup_SyncWrite (pIopcgroup, NumItems, psaHandles, psaValues, psaOut)  
 
if (hr >=0) then 
  hr = SafeArrayAccessData(psaOut, pErrors)  
      ! examine Errors in here.  
  hr = SafeArrayUnAccessData(psaOut)  
 
! ... 
 

hth,
John
0 Kudos
stober123
Beginner
419 Views
Thanks John, that got it!
0 Kudos
Reply