I’m writing a Fortran binding to a C function looking like:
void some_function(int * argument);
Argument is passed as pointer because it can be NULL. The user can pass a pointer to a specific integer value to tune the function’s behavior, or pass NULL to let the function select a reasonable default value.
So far I was binding this with:
subroutine some_function(argument) bind(c)
import :: c_int
integer(c_int) :: argument ! without the "value" attribute
end
But this form forbids passing c_null_ptr
:
call some_function(3)
call some_function(c_null_ptr) ! gfortran: Error: Type mismatch in argument 'argument' at (1); passed TYPE(c_ptr) to INTEGER(4)
This makes me say this binding would be closer to the C++ form:
void some_function(int& argument);
But to bind my C function with nullable argument, I’m forced to write:
subroutine some_function(argument) bind(c)
import :: c_ptr
type(c_ptr), value :: argument
end
So the original type of argument
is lost, and some extra work is required for the caller:
integer, target :: v
v = 3
call some_function(c_loc(v))
call some_function(c_null_ptr) ! This is OK now
As a nasty consequence, it’s now possible to pass anything to my function:
real, target :: u
u = 8.45
call some_function(c_loc(u)) ! Oops
So:
- Is my understanding correct?
- If so, is there another way to do this?
I was considering something hacky:
interface hack
subroutine some_function_int(argument) bind(c, name="some_function")
import :: c_int
integer(c_int) :: argument ! without the "value" attribute
end
subroutine some_function_ptr(argument) bind(c, name="some_function")
import :: c_ptr
type(c_ptr), value :: argument
end
end interface
It seems to work:
integer, target :: v
call hack(3)
call hack(c_null_ptr)
v = 15
call hack(v)
v = 3
call hack(c_loc(v))
With a dummy implementation:
#include <stdio.h>
int some_function(int * value)
{
if(value == NULL)
{
printf("C > value received = NULL !!\n");
}
else
{
printf("C > value received = %d\n", *value);
}
}
I get:
C > value received = 3
C > value received = NULL !!
C > value received = 15
C > value received = 3
But I’m not sure if it works by pure chance, and I’m worried about the legitimacy of this.