- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
Any ideas?
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
-John
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
hth,
John
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks John, that got it!
![](/skins/images/D2683F18326913BBA0436CB7114DD569/responsive_peak/images/icon_anonymous_message.png)
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page