- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The C allocates the space for the variable size array, assigns values, and passes it via a pointer. The Fortran TYPE with pointer receives the memory space OK (no crash) but the values are garbage. I do the ALLOCATE to TARGET array and assign the Pointer to the TARGET but I'm not certain where the memoryis supposed to get"mapped" to the targetarray.
I am using VS2008 x64 for both with IVF 11.1.
I researched the Forum, the IVF mixed language document and the Fortran 2003 book and
having run out of ideas, I'm seeking some advice.
I am attaching a file "C_to_Fortran.txt" which shows the C struct, allocation and assignment,the C calling subroutine, the FORTRAN "TYPE"and receivingsubroutine as well as a print out of the results. Thanks in Advance for any help.
Link Copied
- 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
real, DIMENSION(:), POINTER :: TraceDataArray
points to an array descriptor that maps out the array. It does NOT point to the 1st element of an allocated array (what C/C++ uses).
In your Fortran type use
...
integer(C_PTR) :: cp_TraceDataArray
...
in subroutine use
real, DIMENSION(:), POINTER :: TraceDataArray ! local pointer
...
call C_F_POINTER(SeismicLine%cp_TraceDataArray, TraceDataArray, [SeismicLine%numTraces*SeismicLine%numSamples])
The allocate was performed on the C/C++ side, the array pointer interpretation is performed on the FORTRAN side
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks JIm, I am trying your suggestion,
I included "use ISO_C_BINDING" trying to resolve (C_PTR) and C_F_POINTER..
But I get thse errors:
The first 2 occur where (C_PTR) is declared as in:
integer (C_PTR) :: cp_TraceDataArray
Message 1 remark #5082: Directive ignored - Syntax error, found '(' when expecting one of: :: , : ] C:\agr_dev\Ver1.0\K3F_Utils\K3F_Utils.f90 398
I also triedC_PTRwithout parens
Error 2 error #6683: A kind type parameter must be a compile-time constant. [C_PTR] C:\agr_dev\Ver1.0\K3F_Utils\K3F_Utils.f90 26
The 3rd one :
Error 3 error #6285: There is no matching specific subroutine for this generic subroutine call. [C_F_POINTER] C:\agr_dev\Ver1.0\K3F_Utils\K3F_Utils.f90 454
occurs at
call c_f_pointer(SeismicLine%cp_TraceDataArray, TraceDataArray, [SeismicLine%numTraces*SeismicLine%numSamples])
Is there a specific LIB that I am missing for C_PTR and C_F_POINTER ? Or Propery setting?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[bash]TYPE(C_PTR) :: your_variable_name[/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What about C_F_POINTER, I tried to declare that as well, but couldn't.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The only "declaration" required is the USE ISO_C_BINDING statement.
Check that the first argument to C_F_POINTER is a C_PTR, the second argument is a fortran POINTER with rank "n", and the third argument is an integer array with "n" elements.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am now able to compile C_F_Pointer, thanks, but I'm not quite there yet
When I use the TYPE (C_PTR) as follows I get Error 1 below.
sequence
integer :: numTraces
integer :: numSamples
TYPE (C_PTR) :: cp_TraceDataArray
END TYPE SeismicLineStruct
Error1 error #6027: All derived type fields within a sequenced type must be of a derived-type that is sequenced (R424.2). [CP_TRACEDATAARRAY]C:\agr_dev\Ver1.0\K3F_Utils\K3F_Utils.f9021
- - - - - - - - -
So I tried a different approach in the meantime where I
tried "flattening" thestructure, taking theC_PTR line out of the struct and passing all as separate arguements. This compiles and runs w/o crash but the resulting array values are undefined.
subroutine FProcessSeisLineC ( numTraces, numSamples , TraceDataPtr)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS: 'FProcessSeisLineC' ::FProcessSeisLineC
!DEC$ ATTRIBUTES integer,reference ::numTraces
!DEC$ ATTRIBUTES integer, reference::numSamples
integer(4), intent(IN) :: numTraces !THESE COME THROUGH OK
integer(4), intent(IN) :: numSamples !THESE COME THROUGH OK
TYPE (C_PTR) ,intent(IN) :: TraceDataPtr ! local pointer
real, DIMENSION(:), POINTER :: TraceData ! local pointer
character(LEN=80) Path, errmsg,src !
integer(1) lDim
lDim = numTraces * numSamples; ! Calc size needed
call c_f_pointer( TraceDataPtr, TraceData, [lDim]) ! I TAKEIT THAT THE ALLOCATE IS DONE IN HERE
- - - - - - - - - - - - - - -
I could still use some help to understand why the structure above is complaining about a "sequence type". I
would rather usethe structurethan the flattened approach. Even the flattened approach doesnt quite know how to find the address of the float array malloc'd in C.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The type should include SEQUENCE in the event that a C_PTR is used within a SEQUENCED user type.
! -------------------------------------------------------------------------
! C_PTR, C_FUNPTR, C_NULL_PTR, C_NULL_FUNPTR
! -------------------------------------------------------------------------
TYPE, BIND(C) :: C_PTR
SEQUENCE !**** addsequence here ***
PRIVATE
INTEGER(C_INTPTR_T) :: ptr
END TYPE C_PTR
Wouldn't hurt to do the same for C_FUNPTR
>>call c_f_pointer( TraceDataPtr, TraceData, [lDim]) ! I TAKEIT THAT THE ALLOCATE IS DONE IN HERE
No, the allocation was performed by your C/C++ code.
c_f_pointer is constructing an array descriptor (FORTRAN array pointer).
A FORTRAN array descriptor contains something along the line of:
status
rank
C type pointer to block of memory
lowIndex, highIndex, stride (1st rank)
lowIndes, highIndes, stride (2nd rank)
...
Think of this as a C/C++ object that maps allocated memory (e.g. CSTRING)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The type should include SEQUENCE in the event that a C_PTR is used within a SEQUENCED user type.
I don't think so. BIND(C) states that the TYPE is interoperable (same order and alignment) with "companion C processor". SEQUENCE states that the TYPE is interoperable with other Fortran structures (via sequence association). The two are incompatible, in general case, and user should pick one or another. The type should have BIND(C) attribute, not SEQUENCE.
I don't like SEQUENCE, by the way.
- 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
TYPE (C_PTR) :: cp_TraceDataArray
to
integer(C_INTPTR_T) :: addr_TraceDataArray
Then you can either interpret it as a Cray pointer or use TRANSFER to convert it to TYPE(C_PTR).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I disagree
The OP had a user defined type, of SEQUENCE type, containing a "user defined type" of type C_PTR .AND. type C_PTR is .NOT. a SEQUENCE type. Meaning user could not include member variable of type(C_PTR) (of type .NOT. of sequence type) in his SEQUENCE type type. (requiring additional coding hoops to jump through to use the pointer)
type(C_PTR) is effectively compatible with SEQUENCE type (just as INTEGER or REAL types are compatible with SEQUENCE types, and thus permitted within and enclosing type of sequence type).
Unfortunately, IVF did not determine that the type(C_PTR) only contained a single member variable of type INTEGER(C_INTPTR_T) and thus was compatible with sequence type. IOW no padding or alignment issues.
Inserting SEQUENCE into TYPE(C_PTR) would be benign to existing (working) code, and make a TYPE(C_PTR) permissible in a user defined type of sequence type. So I do not think there is a downside to this.
Your comments would be appreciated.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The standard says that if a type is BIND(C), then it must not be SEQUENCE. SEQUENCE prevents reordering of components but does not guarantee a layout interoperable with the "companion C processor". The standard also says that C_PTR is BIND(C). I think initially we did not define it as such, but it is now.
Yes, that means you can't use C_PTR in a SEQUENCE type. I would argue that SEQUENCE is an obsolete feature and should generally be replaced with BIND(C) in most cases. You can put variables of interoperable derived type in a COMMON, but not in EQUIVALENCE.
We're not going to extend the language in this area. If you are retrofitting existing code, C_PTR may not be the right choice for an address.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
C_to_Fortran.txt
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page