10-232 To: J3 From: Nick Maclaren Subject: Interop TR: Using the CFI_desc_t type Date: 2010 October 08 Reference: 10-165r2 The type CFI_desc_t is an incomplete type. This is no problem when descriptors are passed to C functions, because the type passed is actually a pointer to CFI_desc_t which is a complete type. So the following function declaration (as used in the TR) is fine: int Trivial ( CFI_desc_t * ) ; Using malloc to allocate space for a descriptor of known rank is also straightforward, and the following allocates one of rank 5: CFI_desc_t * desc = (CFI_desc_t *)malloc(sizeof(CFI_desc_t)+5*sizeof(CFI_dim_t)); While this is a bit more verbose, it is clear and that sort of thing is very common in C. It is trivial to hide in a function or macro. The problem arises when one wants to allocate such an object directly. That is likely to be relatively rare, as most descriptors will be passed as arguments. It is also likely to be associated with the creation of allocatable and pointer arrays, when an extra use of malloc() and free() is not a problem. One option is to do nothing and imply that descriptors must always be allocated dynamically. Lots of interfaces have such objects, and that is the way that most of C++ works. OPTION 1: Do nothing. END OPTION 1 There is actually a way to declare a descriptor of known rank statically or on the stack with no extra mechanism, but it relies on a knowledge of the C standard's arcane minutiae and is truly revolting anyway, so I won't bother to describe it. If this facility is regarded as essential, then the TR should define an extra macro to do the job, which is the solution adopted by several interfaces. OPTION 2: The following macro should be defined: Macro CFI_DESC_T The CFI_DESC_T takes one argument, which is the rank of the descriptor to create and evaluates to a type suitable for declaring a descriptor of that rank. A pointer to a variable declared using CFI_DESC_T may be cast to CFI_desc_t *. NOTE ??? The following code uses CFI_DESC_T to declare a descriptor of rank 5 and pass it to CFI_deallocate. CFI_DESC_T(5) object; ... code to initialise and use descriptor ... void *ptr = CFI_deallocate((CFI_desc_t *)&object); END OPTION 2 The macro CFI_DESC_T is trivial to implement, but obviously needs to match the declaration of CFI_desc_t. For example: typedef struct { void * base_addr; size_t elem_len; CFI_rank_t rank; CFI_type_t type; CFI_attribute_t attribute; CFI_state_t state; CFI_dim_t dim[]; } CFI_desc_t; #define CFI_DESC_T(rank) \ struct { \ void * base_addr; \ size_t elem_len; \ CFI_rank_t rank; \ CFI_type_t type; \ CFI_attribute_t attribute; \ CFI_state_t state; \ CFI_dim_t dim[rank]; \ }