- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm trying to get an integer array from an ActiveX device interface.
Being COM it passes the data as a SafeArray.
I thought when I found the post on passing an array of strings from VB that it would have what I need
but I find no documentation on routines like SafeArrayGetLBound, SafeArrayGetUBound and possible other routines I need.
Are those routines documented somewhere, or do I need to resort to writing my own routines in C++ to access this safe array of Ints? Clearly I don't want to use SafeArrayGetElement to access a large array of values.
What SafeArray routines are available for Intel Visual Fortran? Currently I have version 11.1, but I should be receiving version 12 this week
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Others will probably chime in with more experience with SafeArrays, but I wanted to point out from our documentation on QuickWin:
An array is always passed as a SafeArray ByRef. Therefore it must be defined with Intent set to InOut
This from the section in the documentation, titled:
Fortran COM Server Interface Design Considerations
The documenation should be installed on your system (for 11.1):
Start -> All Programs => Intel Software Development Tools => Intel Fortran Compiler X.X.XXX => Intel Visual Fortran Documentation
Hope this helps,
------
Wendy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So, there is documentation for the SafeArray routines in the C++ help of Visual Studio,
and they seem to carry over to IVF with the IFWINTY module.
The AUTOINVOKE routine, returns the VARIANT in $RETURN, and %RETURN%VU%PTR_VAL does indeed point to the desired SafeArray
And, STATUS = SafeArrayAccessData( $RETURN%VU%PTR_VAL, pInt4)
where I have>> integer (kind=4), pointer ::pInt4
does indeed point to the desired data
but when I attempt to copy the data to my array from there, so that I can free the $RETURN buffer,
the compiler doesn't like
>> do i=1, Length
>> mydata(i) = pInt4(i)
>>end do
It complains that pInt4 wasn't declared with a dimension.
But, SafeArrayAccessData doesn't like it when it is declared with a dimension.
Any ideas what I need to do to actually get at my data?
any help appreciated, thank.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try this instead:
STATUS = SafeArrayAccessData($Return%vu%ptr_val, LOC(mydata))
where mydata(:) has been declared as an integer array.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem is that the second argument to SafeArrayAccessData has either INTENT(OUT) or INTENT(INOUT), and so LOC() is not allowed as it is a constant and so can't be changed in the routine.
I did try preceeding the call to AUTOINVOKE (for the COM getdata routine) with
$RETURN%VU%PTR_VAL=LOC(mydata), but it simply gets overwritten by the AUTOINVOKE call
Three other items:
1) integer (kind=4), pointer :: pInt4(:) SafeArrayAccessData complains about a shape mismatch
2) If I leave out the call to anySafeArray routines, my program executes cleanly (although it accomplishes little) but it I include the call to SafeArrayAccessData or include it and also the UnaccessData routine, and also if I include those two and also SafeArrayDestroyData in an attempt to clean things up,
THEN (in any of those cases) I get stack problems -- so I'm clearly not cleaning up correctly. The safe array is being created in the COM call, so I wouldn't think I should be explicitly destroying it in my routine.
3) in the VisualStudio C++ example for variants and SafeArrays, it uses SafeArrayCreate to create and SafeArrayDestroy to destroy the safe array, and SafeArrayAccessData and SafeArrayUnaccessData to access and release a pointer to the data. The 2nd argument to the Access routine is declared as
int* pData; and the 2nd argument is (void**) &pData so it's passing the pointer by reference, passing the address of the pointer.
I'm still using version 11.1 -- is it not compatible with receiving a SafeArray from a COM object?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You might want to reference the sample we include in our product about Safe Arrays and Visual Basic in the Mixed Language samples. Samples are installed by default at:
C:\Program Files\Intel\Compiler\11.1\xxx\Samples
the sample is in: MixedLanguage\VB.NET-SafeArrays\
------
Wendy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Got it
I was making this too hard
declare integer (kind=4) Int4_vals(256)
pointer (pInt4, Int4_vals)
type (variant), volatile :: $RETURN
integer(int_ptr_kind()) invokeargs
.
.
.
invokeargs = autoallocateinvokeargs()
call autoaddarg(invokeargs, '$RETURN', $RETURN, AUTO_ARG_OUT)
.
status = autoinvoke(pOBJECT, mID, invokeargs)
! Return%VU%PTR_VAL contains a pointer to a pointer to the safe array
pInt4 = $RETURN%VU%PTR_VAL ! now Int4_vals(1) has the pointer to the data
pIint4 = Int4_vals(1) ! now Int4_vals(1:256) is the data in the safe array
do i=1,256
mydata(I) = Int4_vals(I)
end do
call autodeallocateinvokeargs(invokeargs) ! now done with the safearray and $RETURN
.
.
The C++ examples says not to access the data directly -- Does anyone know anything about that? Is something going to bite me if I do it this way?
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After think back over my experience I realized some of my trouble with those routines was operator error, apparently connected to my naming of the routine I was calling.
Now I'm using the function produced by the Fortran Module Wizard, which returns a VARIANT
pInt4 is defined like previous post with pointer (pInt4,vec) with INTEGER (kind=4) vec(512)
HRESULT = AUTOGetProperty (OBJ_Comm, 30, nActive, vt_I4) ! get active size of data
pyvals = $DUMCBICONN2_GetData1(OBJ_Comm, 0, nActive-1, HRESULT) ! get all the data
! pyvals points to VARIANT, pyvals%VU%PTR_VAL points to SafeArray
HRESULT = SafeArrayAccessData(pyvals%VU%PTR_VAL, pInt4)
do i = 1, nActive
ycounts(i) = vec(i)
end do
HRESULT = SafeArrayUnaccessData(pyvals%VU%PTR_VAL)
and this works just fine. Of course both vec and ycounts must be large enough or there is a subscript complaint when"i" gets too large.
It would be nice if vec could be allocatable, so that I could ensure it was large enough without having to just use the largest possible value.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I guess I get a little confused with some of the changes from 66 to 77 to 90 to 95 to ...
integer (kind=4) vec(*)
pointer (pInt4, vec)
compiles just fine.
I was thinking that it wouldn't like declaration of vec(*) because I was used to only doing that for arguments passed into the routine. Three and more decades back. Good to know.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is therea way to accomplish this within one of the Fortran standards?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm having a similar problem passing an array to a vb.net COM. I've seen several examples of people having similar problems but I haven't found a complete solution that shows the .net code as well as the Fortran code. It sounds like you may have found a solution to this but I can't quite piece together your code segments to figure out what I need to do. Would it be possible for you to provide your complete code as an example? The module wizard creates the following for one of my vb.net test functions. I've tried Marshaling the array in vb as a safearray but am not sure what to do on both the vb and Fortran sides. Any advice or examples from anyone would be appreciated.
I can't figure out what to pass to A1. I've tried passing a safearray wrapped in a variant based on the following code example but there is a type mismatch.
http://origin-software.intel.com/en-us/forums/showthread.php?t=64908
REAL(4) FUNCTION $Graphics_SumArrayA($OBJECT, A1, $STATUS)
IMPLICIT NONE
INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
REAL(4), DIMENSION(:), INTENT(INOUT), VOLATILE :: A1 ! (SafeArray)
!DEC$ ATTRIBUTES REFERENCE :: A1
INTEGER(4), INTENT(OUT), OPTIONAL :: $STATUS ! Method status
!DEC$ ATTRIBUTES REFERENCE :: $STATUS
REAL(4), VOLATILE :: $RETURN
INTEGER(4) $$STATUS
INTEGER(INT_PTR_KIND()) invokeargs
invokeargs = AUTOALLOCATEINVOKEARGS()
CALL AUTOADDARG(invokeargs, '$RETURN', $RETURN)
CALL AUTOADDARG(invokeargs, '$ARG1', A1, AUTO_ARG_INOUT)
$$STATUS = AUTOINVOKE($OBJECT, 1610743812, invokeargs)
IF (PRESENT($STATUS)) $STATUS = $$STATUS
$Graphics_SumArrayA = $RETURN
CALL AUTODEALLOCATEINVOKEARGS (invokeargs)
END FUNCTION $Graphics_SumArrayA

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page