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

problem about defining "NULL"

pumbt
Beginner
857 Views
Hi all. My fortran code is linked with library generated with C code. In the C function the default value for a parameter is "NULL". In calling this function, I tried to use 0 for this parameter and it seems the C function works without problem. However, I would like to know is there a more consistent way to define "NULL"?
Many thanks.
0 Kudos
1 Reply
JVanB
Valued Contributor II
857 Views
In the general case one has to look at the interface body you wrote to describe the C function to the Fortran compiler to know what to do.Some cases are simple: if the C prototype describes the argument as "int x", then the interface body will describe it as "integer(C_INT), value :: x", and then passing 0_C_INT or even 0 as actual argument is fine.

If the prototype reads "intptr_t x", then the interface body will read "integer(C_INTPTR_T), value :: x" and you will want to pass 0_C_INTPTR_T as actual argument because simply 0 will be non-conforming on 64-bit platforms.

Now, the interesting cases arise when the C prototype expects a pointer rather than in integer by value. Suppose the C function expects a pointer to an array of ints, a pointer which may be NULL. The C prototype specifies an argument of "int *A", but the Fortran interface body could be written in one of two ways:
1) integer(C_INT) A(*), so that to pass an array starting with integer(C_INT), allocatable :: B(:), one would first allocate(B(100)), then B=1, then use B as actual argument, passing an array of 100 copies of 1. But then to pass NULL for argument A, you would have to define a pointer: integer(C_INT), pointer :: C(:), then makes its address NULL with call C_F_POINTER(C_NULL_PTR,C,[1]), then passing C as actual argument would pass C_NULL_PTR, i.e. NULL to the C function.
2) type(C_PTR), value :: A, so that to pass an array starting with integer(C_INT), allocatable, target :: B(:), one would again first allocate(B(100)), then B=1, but now you need to pass C_LOC(B(1)) as actual argument. To pass NULL in this case is easy: just pass C_NULL_PTR.

Similar considerations arise when your C function wants a function pointer as an argument. C can never pass a function, only a function pointer. Sometimes C has an actual argument which is a pointer to a pointer, such as int **p. Now just what is meant by NULL, whether you are supposed to pass a pointer which points to a valid address, but the value contained at that address is NULL, or whether you are supposed to pass a pointer whose value is NULL is a question you will have to determine from the documentation of the C function. Once you know the level of indirection of the NULL that must be passed, there are two possible levels of indirection for the Fortran interface body, whether it specifies type(C_PTR), value :: p or type(C_PTR) p. Given that there are now 4 cases to talk about and that the same issue can arise for pointers to function pointers, I will stop at this point.
0 Kudos
Reply