Skip to content

Instantly share code, notes, and snippets.

@alanbriolat
Last active February 10, 2021 16:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alanbriolat/feeabde501f1568cfa19 to your computer and use it in GitHub Desktop.
Save alanbriolat/feeabde501f1568cfa19 to your computer and use it in GitHub Desktop.
Fortran BIND(C) optional arguments
void do_the_thing(int*, double*, double*, double*);
extern const int blah;
int main(int argc, char **argv)
{
int n = 5;
double x[5] = {1, 2, 3, 4, 5};
double y[5] = {10, 20, 30, 40, 50};
double z[5];
do_the_thing(&n, x, y, z);
do_the_thing(&n, x, 0, z);
return 0;
}
module foo
use iso_c_binding
implicit none
private
public :: do_the_thing
integer(c_int), public, bind(c) :: blah = 12
contains
subroutine do_the_thing(n, x, y, z) bind(c)
integer(c_int), intent(in) :: n
real(c_double), dimension(n), intent(in) :: x
real(c_double), dimension(n), intent(in), optional :: y
real(c_double), dimension(n), intent(out) :: z
if (present(y)) then
print *, "Y is present"
else
print *, "Y is not present"
end if
z = x
if (present(y)) then
z = z + y
end if
end subroutine do_the_thing
end module foo
import cffi
ffi = cffi.FFI()
ffi.cdef("""
void do_the_thing(int*, float*, float*, float*);
extern const int blah;
""")
api = ffi.dlopen('./libfoo.so')
n = ffi.new('int[1]', [5])
x = ffi.new('float[]', [1, 2, 3, 4, 5])
y = ffi.new('float[]', [10, 20, 30, 40, 50])
z = ffi.new('float[]', 5)
api.do_the_thing(n, x, y, z)
api.do_the_thing(n, x, ffi.NULL, z)
print(api.blah)
$ gfortran bind_c_optional.f90 bind_c_optional.c
$ ./a.out
Y is present
Y is not present
12
$ gfortran -shared -fPIC -o libfoo.so bind_c_optional.f90
$ python bind_c_optional.py
Y is present
Y is not present
Traceback (most recent call last):
File "bind_c_optional.py", line 19, in <module>
print(api.blah)
File "/usr/lib/python2.7/dist-packages/cffi/api.py", line 460, in __getattr__
make_accessor(name)
File "/usr/lib/python2.7/dist-packages/cffi/api.py", line 456, in make_accessor
make_accessor_locked(name)
File "/usr/lib/python2.7/dist-packages/cffi/api.py", line 450, in make_accessor_locked
raise AttributeError(name)
AttributeError: blah
$ nm libfoo.so | grep -E "blah|do_the_thing"
0000000000201048 D blah
00000000000007d5 T do_the_thing
$ gcc bind_c_optional.c -lfoo -L.
$ LD_LIBRARY_PATH=. ./a.out
Y is present
Y is not present
12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment