Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29274 Discussions

Passing derived-types with pointer to vector From F90 to c

jsn
Beginner
720 Views
Is it possible to create a Fortran TYPE that maps on to a c struct that contains a pointer to a double vector? For example, I would like to be able to create an object of the type VEC within CVF and pass it to the c function (VEC_WRITE) for printing to a text-file:

C (VC++):
typedef struct _VEC VEC;
struct _VEC {
int size ;
double *pvec ;
} ;
VEC_write (
VEC *a,
char *filename
) ;
FORTRAN95 (CVF6.6):
TYPE VEC
INTEGER :: size;
real(DP), pointer, dimension(:) :: pvec=>null() ;
ENDTYPE VEC
TYPE(VEC) :: aVec
aVec%size = 5
allocate(aVec%pvec(aVec%size))
aVec%pvec = 5
CALL VEC_write(aVec, "out.txt")
0 Kudos
4 Replies
Jugoslav_Dujic
Valued Contributor II
720 Views
real(DP), pointer, dimension(:) is actually implemented as a descriptor; you can find its description (it can be mapped to a C struct) on page "Handling Arrays and Visual Fortran Array Descriptors" in "Programming with Mixed Languages" chapter of Programmer's Guide. For 1-D array it will be 28 bytes long, if I recall correctly.

But trying to match it with a C struct and extract the info from C code could be a pain. It's easier to pass just the address and size of the array:
extern "C" void __stdcall VEC_write(int size, double* pvec)
...
call VEC_write(aVec%size, loc(aVec%pVec))
If there's a lot of arrays within the real structure, you may define a type used only for transport, containing only integers, e.g.:
TYPE VEC_transport
   integer:: size
   integer(INT_PTR_KIND()):: pVec
END TYPE VEC_transport
...
FUNCTION CastToCVec(aVec) RESULT(VT)
TYPE(VEC_transport):: VT
TYPE(VEC), INTENT(IN):: aVec
!
VT%size = aVec%size
VT%pVec = LOC(aVec%pVec)
!
END FUNCTION CastToCVec
...
call VEC_write(CastToCVec(aVec))
Jugoslav

0 Kudos
Steven_L_Intel1
Employee
720 Views
Also, you need to add SEQUENCE to the TYPE definition to prevent the compiler from inserting padding and possibly rearranging the elements.

Steve
0 Kudos
jsn
Beginner
720 Views
Thank you,

Your suggestion worked.
I have also been able to associate the retruned c-pointer to double-vector with a pointer-descriptor. SO, now I can use the double-vector naturally within fortran.

JSN
0 Kudos
Jugoslav_Dujic
Valued Contributor II
720 Views
A side note: CVF 6.6B now supports ALLOCATABLE components of derived types -- it will be a part of Fortran 2000 standard. It's usually what people need in this context, and they're superior to pointers in the sense that they can never leak memory (they're automatically DEALLOCATEd when the parent goes out of scope), and have some other handy properties (e.g. with POINTER components,

Vec1=Vec2 means Vec1%pVec => Vec2%pVec,

while with ALLOCATABLEs

Vec1=Vec2 means
DEALLOCATE(Vec1%pVec);
ALLOCATE(Vec1%pVec(SIZE(Vec2%pVec));
Vec1%pVec = Vec2%pVec).

As far as I know, the underlying implementation in CVF is the same (28-byte descriptor).

Jugoslav
0 Kudos
Reply