Last active
February 10, 2021 16:55
-
-
Save alanbriolat/feeabde501f1568cfa19 to your computer and use it in GitHub Desktop.
Fortran BIND(C) optional arguments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ 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