- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is there a way to get the calling interface right for a program compiled with CVF to call routines in a DLL compiled with IVF? I must be missing something, because my arrays are all messed up.
Here is the interface for one of the routines in the DLL:
The routine is called with:
The SIZE function returns 4, 4, and 40 for the arrays 'int_arr', 'real_arr', and 'char_arr', respectively, instead of the actual values of 20, 50, and 5. Only the first element of each of the arrays has the correct value. The DLL compiled in IVF has the iface:/cvf option, although I don't see from the documentation that it has anything to do with arrays.
Here is the interface for one of the routines in the DLL:
interface
subroutine USERHARNESS(i, j ,int_arr, char_arr, real_arr, dt, u, y)
integer, intent(in) :: i, j
integer, dimension(:), intent(in) :: int_arr
character(len=40), dimension(:), intent(in) :: char_arr
real, dimension(:), intent(in) :: real_arr
real, intent(in) :: dt
real, dimension(:), intent(in) :: u
real, dimension(:), intent(out) :: y
end subroutine USERHARNESS
end interface
The routine is called with:
call USERHARNESS(i, j, int_arr(:,j), char_arr(:,j), real_arr(:,j), dt, u(:,k), y(:,k))
The SIZE function returns 4, 4, and 40 for the arrays 'int_arr', 'real_arr', and 'char_arr', respectively, instead of the actual values of 20, 50, and 5. Only the first element of each of the arrays has the correct value. The DLL compiled in IVF has the iface:/cvf option, although I don't see from the documentation that it has anything to do with arrays.
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You're getting help on this through Intel Premier Support and I assisted the support engineer who has the case, so you should be getting the answer very soon. Briefly, you're passing assumed-shape arrays between CVF and IVF and this doesn't work because the descriptor layouts are incompatible. An option is to change to adjustable arrays where the bounds are passed as separate arguments.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If redesign/recompile is not a viable choice for one reason or another, it is possible to write a wrapper routine which would convert CVF array descriptors to IVF ones. I can post a sample, but I'd rather not unless you have no other choice, because that solution is a very ugly hack and should be used as last resort.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve and Jugoslav. I'd come to the conclusion that I'd have to make a wrapper to support both compilers right now. It may be ugly, but it works for me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
BTW, the difference is that the Intel compiler sticks an extra 32-bit value that is initialized to zero and reserved for compiler use.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Attached is a complete solution with dummy functionality. I assumed that the dll will be compiled only with IVF, and the caller can be compiled with both CVF and IVF. Also, I assumed default calling conventions for both compilers (thus the longish list of attributes for the dll exported routine, so that CVF knows how to call the VF dll correctly).
The key routine (containing most of ugliness) is:
The key routine (containing most of ugliness) is:
Wrapper routine for dll. Must be external, as we are going to cheat the compiler
!about types.
subroutine USERHARNESS_W(i, j ,int_arr, char_arr, real_arr, dt, u, y)
!NB: all the assumed-shape arrays are replaced with assumed-size. Actually,
!we will get 7 (8) - byte descriptors for real arguments in there, and pass
!them into the dll unmodified (for IVF caller) or fixed (for CVF caller)
integer, intent(in) :: i, j
integer, intent(in) :: int_arr(*)
integer, intent(in) :: char_arr(*)
integer, intent(in) :: real_arr(*)
real, intent(in) :: dt
integer, intent(in) :: u(*)
integer, intent(in) :: y(*)
interface
subroutine USERHARNESS(i, j ,int_arr, char_arr, real_arr, dt, u, y)
!DEC$ATTRIBUTES DLLIMPORT, C, DECORATE, REFERENCE,
NOMIXED_STR_LEN_ARG, ALIAS: "USERHARNESS":: USERHARNESS
integer, intent(in) :: i, j
integer, intent(in) :: int_arr(*)
integer, intent(in) :: char_arr(*)
integer, intent(in) :: real_arr(*)
real, intent(in) :: dt
integer, intent(in) :: u(*)
integer, intent(in) :: y(*)
end subroutine USERHARNESS
end interface
!DEC$IF DEFINED(__INTEL_COMPILER)
call USERHARNESS(i, j, int_arr, char_arr, real_arr, dt, u, y)
!DEC$ELSE
call USERHARNESS(i, j, IVF(int_arr), IVF(char_arr), IVF(real_arr), dt, IVF(u), IVF(y))
!DEC$ENDIF
contains
function IVF(arr)
!Converts CVF array descriptor on input to VF ones. 1-D descriptors are
! - 5+3 dwords for CVF
! - 6+3 dwords for IVF (zero on 6th position)
!2-D descriptors are
! - 5+3+3 dwords for CVF
! - 6+3+3 dwords for IVF (zero on 6th position)
!Since the result is temporary stack array, we may size it to max size (12).
!Thus, we'll copy some garbage if only 1-D arrays are used, but it doesn't
!matter, as they won't be used. Reduce the sizes to 8/9 if you work only
!with 1-D arrays.
integer:: IVF(12)
integer, intent(in):: arr(11)
IVF(1:5)=arr(1:5)
IVF(6)=0
IVF(7:12)=arr(6:11)
end function IVF
end subroutine USERHARNESS_W

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