- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
We are trying to access a dynamic array in DVF COM server using Visual Basic.Net as follows. A VB.Net Executable calls a VB.Net DLL, which in turn calls a Property Get function in the Fortran COM Server to return the dynamic array (see Figure). This call is made via a .NET runtime callable wrapper (RCW) that was created by using the TLBIMP command.
VB.Net Executable
|
VB.Net DLL
|
Runtime Callable Wrapper (RCW)
|
Fortran COM Server
Our Fortran COM Server was developed using DVF 6.6B.
The DVF COM Server Wizard was used to add the COM Server methods and properties. Y1 is the property that is used to return the dynamically allocated array as a safearray. Note that an array is passed from COM to .NET as a safearray. As DVF COM Server Wizard can only output fixed length array in Property Get, we modified ITransform1.f90 (Transform1 is the name of our program) as shown below. Note that we manually filled in the safearray descriptor based on the size of the dynamic array in our COM server. (see code below)
We are able to correctly access the dynamic array via the Y1 property when the VB.Net DLL is NOT a ServicedComponent. However if the VB.Net IS a ServicedComponent (runs in Component Services as a COM Server) then we encounter a SafeArrayTypeMismatchException error when we attempt to access the dynamic array via theY1 property (Note that the Y1 property returns the safearray).
We do not know what caused the error after extensive search on the Internet. Could you give us some suggestion on what may have caused the problem and what we could try to resolve it. Thank you.
Lawrence
function $ITransform1_get_Y1( pInterface ,&
VALUE ) result (hresult)
!DEC$ ATTRIBUTES STDCALL :: $ITransform1_get_Y1
use CTransform1_Types
use dfcom
use dflib
implicit none
type (ITransform1_Ptr) pInterface
!dec$ attributes reference :: pInterface
integer(INT_PTR_KIND()), intent(out) :: VALUE
!DEC$ ATTRIBUTES reference :: VALUE
integer(LONG) hresult
integer i
REAL(8) f$VALUE(:)
VOLATILE f$VALUE
POINTER f$VALUE
integer(INT_PTR_KIND()) ptr$VALUE
integer(INT_PTR_KIND()) sa$VALUE
type(T_SAFEARRAY) sad$VALUE
pointer(ptrsad$VALUE, sad$VALUE)
type(T_SAFEARRAYBOUND) sab$VALUE(1)
pointer(ptrsab$VALUE, sab$VALUE)
type (FOR_DIMS_INFO) da$VALUE(1)
INTEGER(4) iLBound
INTEGER(4) iUBound
INTEGER(4) iElements
sa$VALUE = NULL
iLBound = 0
iUBound = UBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1) - &
LBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1)
iElements = (iUBound - iLBound) + 1
hresult = SafeArrayAllocDescriptor(1, sa$VALUE)
if (hresult < 0) goto 9999
ptrsad$VALUE = sa$VALUE
sad$VALUE % cbElements = 8
ptrsab$VALUE = loc(sad$VALUE % rgsabound(1))
sab$VALUE(1) % cElements = iElements
sab$VALUE(1) % lLbound = iLBound
hresult = SafeArrayAllocData(sa$VALUE)
if (hresult < 0) goto 9999
hresult = SafeArrayAccessData(sa$VALUE, ptr$VALUE)
if (hresult < 0) goto 9999
!Move the data from Y1 into the SafeArray
da$VALUE(1)%LowerBound = LBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1)
da$VALUE(1)%UpperBound = UBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1)
da$VALUE(1)%Stride = 1
call FOR_DESCRIPTOR_ASSIGN(f$VALUE, ptr$VALUE, SIZEOF(f$VALUE(iLBound)), &
IOR(FOR_DESCRIPTOR_ARRAY_DEFINED, IOR(FOR_DESCRIPTOR_ARRAY_NODEALLOC, FOR_DESCRIPTOR_ARRAY_CONTIGUOUS)), &
1, da$VALUE)
f$VALUE = pInterface % pInternalData % pInstanceData % Y1
if (hresult < 0) goto 9999
9999 continue ! Cleanup code
if (sa$VALUE /= NULL) i = SafeArrayUnaccessData(sa$VALUE)
VALUE = sa$VALUE
end function
We are trying to access a dynamic array in DVF COM server using Visual Basic.Net as follows. A VB.Net Executable calls a VB.Net DLL, which in turn calls a Property Get function in the Fortran COM Server to return the dynamic array (see Figure). This call is made via a .NET runtime callable wrapper (RCW) that was created by using the TLBIMP command.
VB.Net Executable
|
VB.Net DLL
|
Runtime Callable Wrapper (RCW)
|
Fortran COM Server
Our Fortran COM Server was developed using DVF 6.6B.
The DVF COM Server Wizard was used to add the COM Server methods and properties. Y1 is the property that is used to return the dynamically allocated array as a safearray. Note that an array is passed from COM to .NET as a safearray. As DVF COM Server Wizard can only output fixed length array in Property Get, we modified ITransform1.f90 (Transform1 is the name of our program) as shown below. Note that we manually filled in the safearray descriptor based on the size of the dynamic array in our COM server. (see code below)
We are able to correctly access the dynamic array via the Y1 property when the VB.Net DLL is NOT a ServicedComponent. However if the VB.Net IS a ServicedComponent (runs in Component Services as a COM Server) then we encounter a SafeArrayTypeMismatchException error when we attempt to access the dynamic array via theY1 property (Note that the Y1 property returns the safearray).
We do not know what caused the error after extensive search on the Internet. Could you give us some suggestion on what may have caused the problem and what we could try to resolve it. Thank you.
Lawrence
function $ITransform1_get_Y1( pInterface ,&
VALUE ) result (hresult)
!DEC$ ATTRIBUTES STDCALL :: $ITransform1_get_Y1
use CTransform1_Types
use dfcom
use dflib
implicit none
type (ITransform1_Ptr) pInterface
!dec$ attributes reference :: pInterface
integer(INT_PTR_KIND()), intent(out) :: VALUE
!DEC$ ATTRIBUTES reference :: VALUE
integer(LONG) hresult
integer i
REAL(8) f$VALUE(:)
VOLATILE f$VALUE
POINTER f$VALUE
integer(INT_PTR_KIND()) ptr$VALUE
integer(INT_PTR_KIND()) sa$VALUE
type(T_SAFEARRAY) sad$VALUE
pointer(ptrsad$VALUE, sad$VALUE)
type(T_SAFEARRAYBOUND) sab$VALUE(1)
pointer(ptrsab$VALUE, sab$VALUE)
type (FOR_DIMS_INFO) da$VALUE(1)
INTEGER(4) iLBound
INTEGER(4) iUBound
INTEGER(4) iElements
sa$VALUE = NULL
iLBound = 0
iUBound = UBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1) - &
LBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1)
iElements = (iUBound - iLBound) + 1
hresult = SafeArrayAllocDescriptor(1, sa$VALUE)
if (hresult < 0) goto 9999
ptrsad$VALUE = sa$VALUE
sad$VALUE % cbElements = 8
ptrsab$VALUE = loc(sad$VALUE % rgsabound(1))
sab$VALUE(1) % cElements = iElements
sab$VALUE(1) % lLbound = iLBound
hresult = SafeArrayAllocData(sa$VALUE)
if (hresult < 0) goto 9999
hresult = SafeArrayAccessData(sa$VALUE, ptr$VALUE)
if (hresult < 0) goto 9999
!Move the data from Y1 into the SafeArray
da$VALUE(1)%LowerBound = LBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1)
da$VALUE(1)%UpperBound = UBound(pInterface % pInternalData % pInstanceData % Y1, DIM = 1)
da$VALUE(1)%Stride = 1
call FOR_DESCRIPTOR_ASSIGN(f$VALUE, ptr$VALUE, SIZEOF(f$VALUE(iLBound)), &
IOR(FOR_DESCRIPTOR_ARRAY_DEFINED, IOR(FOR_DESCRIPTOR_ARRAY_NODEALLOC, FOR_DESCRIPTOR_ARRAY_CONTIGUOUS)), &
1, da$VALUE)
f$VALUE = pInterface % pInternalData % pInstanceData % Y1
if (hresult < 0) goto 9999
9999 continue ! Cleanup code
if (sa$VALUE /= NULL) i = SafeArrayUnaccessData(sa$VALUE)
VALUE = sa$VALUE
end function
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
At the risk of reminding you of something you might already know, VB .NET arrays are stored in row-major order whereas in VB .NYET they are stored in column-major order just as in Fortran.
HTH,
Gerry T.
HTH,
Gerry T.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"Nyet" as "No" in Russian or what? :-)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
.NYET = NOT(.NET), ergo VB.NYET = VB6,5,4,...
HTH,
Gerry T.
HTH,
Gerry T.

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