- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm trying to do some black magic.....namely, I've created a C routine which performs a memset() on the array or structure passed to it:
typedef ptrdiff_t CFI_type_t; typedef struct CFI_dim_t_ { CFI_index_t extent; CFI_index_t sm; CFI_index_t lower_bound; } CFI_dim_t; typedef struct CFI_cdesc_t_ { void *base_addr; size_t elem_len; int version; CFI_attribute_t attribute; CFI_rank_t rank; CFI_type_t type; // Begin Intel-specific fields - these are for // Intel compiler/library use only and should // not be modified intptr_t intel_flags; intptr_t intel_reserved1; intptr_t intel_reserved2; // End Intel-specific fields CFI_dim_t dim[]; } CFI_cdesc_t; void fortran_init( CFI_cdesc_t *a ) { memset( a->base_addr, 0, a->elem_len ); return; }
My Fortran interface definition goes as such:
INTERFACE SUBROUTINE FORTRAN_INIT( A ) BIND(C, NAME='fortran_init') IMPLICIT NONE CLASS (*), INTENT(IN) :: A END SUBROUTINE FORTRAN_INIT END INTERFACE
When I compile this using version 15.0.2, everything works fine, and the execution behaves as-expected (I can view all the descriptor properties in the debugger). However, when I compile with the newest version of ifort, I get the following:
#8789: Polymorphic dummy argument to a BIND(C) procedure is not interoperable.
Should I be using a different prototype on the Fortran side to get the CFI_cdesc_t descriptor passed to it properly?
Thanks in advance.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The error message is correct - polymorphic entities are not interoperable.
First, please do NOT try to roll your own declarations of the CFI structures. ONLY, ONLY, ONLY! use ISO_Fortran_binding.h!
What you probably want instead is:
INTERFACE SUBROUTINE FORTRAN_INIT( A ) BIND(C, NAME='fortran_init') IMPLICIT NONE TYPE(*), DIMENSION(..), INTENT(OUT) :: A END SUBROUTINE FORTRAN_INIT END INTERFACE
Note that I said INTENT(OUT) - you had INTENT(IN) which is not what you're doing!
Your C routine is setting only the first element. I doubt that's what you intended. You'd need to compute the number of elements by iterating through the extents.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Actually, it is always my preference to use compiler-provided headers, but in this case, I only have iso_c_binding.f90 and not ISO_Fortran_binding.h in my installation (there are other C header files in the compiler's include folder, but not that). Where should I be looking for this header? I believe I got those definitions from the compiler documentation. I checked .../composerxe-2015.2.164/compiler/include, and actually searched the entire compiler installation path, but no dice.
And yes, thanks for pointing out my incorrect INTENT, though shouldn't it be INOUT? Or does INOUT only refer to the data pointed to, not the CFI structure itself?
Our internal documentation specifies explicitly that this is only for one-dimensional arrays; in the future we may expand it to include the higher-order dimensions, but our immediate needs were only for large 1-D vectors.
However, with the above proposed alternative, I receive:
error #5082: Syntax error, found ',' when expecting one of: , <END-OF-STATEMENT> ; TYPE(*), DIMENSION(..), INTENT(OUT) :: A -------^ error #5082: Syntax error, found '.' when expecting one of: <IDENTIFIER> TYPE(*), DIMENSION(..), INTENT(OUT) :: A --------------------^ error #6404: This name does not have a type, and must have an explicit type.
...unless you had meant I was supposed to replace the (..) with the requested dimension, but in this case, the intention was for Fortran to pass me all of the dimension info in the CFI structure, so I can do as-needed on the C side of things.
P.S. -- The first error message is intriguing: "Error: I found 'FOO' when I was really expecting 'FOO'." ??
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
".. I've created a C routine which performs a memset() .. " - how do you plan to use it?
#include <stdio.h> #include "ISO_Fortran_binding.h" void init_data(CFI_cdesc_t *some_data) { size_t data_size; int i; data_size = some_data->elem_len; for (i=0; i<some_data->rank; i++) { data_size *= some_data->dim.extent; } memset(some_data->base_addr, 0, data_size); }
module m implicit none private interface subroutine init_data( some_data ) bind(C, name="init_data") implicit none type(*), intent(inout) :: some_data(..) end subroutine init_data end interface public :: init_data end module m
program p use m, only : init_data blk1: block integer :: foo foo = 42 print *, "before init_data: foo = ", foo call init_data( foo ) print *, "after init_data: foo = ", foo end block blk1 blk2: block integer :: bar(2,3) bar = 42 print *, "before init_data: bar = ", bar call init_data( bar ) print *, "after init_data: bar = ", bar end block blk2 stop end program p
Upon execution using compiler 17 update 1,
before init_data: foo = 42 after init_data: foo = 0 before init_data: bar = 42 42 42 42 42 42 after init_data: bar = 0 0 0 0 0 0
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You may be using an old version of the compiler. ISO_Fortran_binding.h is supplied in the Fortran include folder, not the C include folder. The (..) syntax (and TYPE(*)) are part of the Fortran 2015 "Further interoperability with C" features supported in compiler version 16.
I explicitly used DIMENSION(..), assumed-rank, as this triggers passing the argument by C descriptor. It allows any rank, including scalar, to be passed. FortranFan shows how to do it.
INTENT(OUT) is correct here as your C routine doesn't ever reference the data before zeroing it.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page