swig-fortran / swig

This fork of SWIG creates Fortran wrapper code from C++ headers.
http://www.swig.org
Other
43 stars 11 forks source link

Pure fortran access to global variables #43

Closed sethrj closed 6 years ago

sethrj commented 6 years ago

For a namespaced/static mutable global variable Foo::global_ctr, you can do this

int* const global_ctr_ptr = &Foo::global_ctr;
module temp
    use, intrinsic :: ISO_C_BINDING
    implicit none

    type(C_PTR), protected, &
        bind(c, name='global_ctr') :: global_ctr_ptr

    public
contains

subroutine set_global_ctr(val)
    use, intrinsic :: ISO_C_BINDING
    integer(C_INT), intent(out) :: val
    integer(C_INT), pointer :: global_ctr
    call c_f_pointer(global_ctr_ptr, global_ctr)
    global_ctr = val
end subroutine

end module

This compiles to:

    movq    _global_ctr@GOTPCREL(%rip), %rax    #, tmp91
    movl    (%rdi), %edx    # *val_3(D), D.3457
    movq    (%rax), %rax    # global_ctr_ptr, global_ctr_ptr
    movl    %edx, (%rax)    # D.3457, *global_ctr_2
    ret
sethrj commented 6 years ago

The current SWIG equivalent C code is:

subroutine set_global_counter(value0)
use, intrinsic :: ISO_C_BINDING
integer(C_INT), intent(in) :: value0
integer(C_INT) :: farg1 

farg1 = value0
call swigc_set_global_counter(farg1)

end subroutine

and

SWIGEXPORT void swigc_set_global_counter(int const *farg1) {
  int arg1 ;

  arg1 = *farg1;
  foo::global_counter = arg1;
 }

which compile to

    .globl ___simple_class_MOD_set_global_counter
___simple_class_MOD_set_global_counter:
LFB15:
    subq    $24, %rsp   #,
LCFI34:
    movl    (%rdi), %eax    # *value0_2(D), *value0_2(D)
    leaq    12(%rsp), %rdi  #, tmp90
    movl    %eax, 12(%rsp)  # *value0_2(D), farg1
    call    _swigc_set_global_counter   #
    addq    $24, %rsp   #,

and

    movl    (%rdi), %eax    # *farg1_2(D), arg1
    movl    %eax, __ZN3foo14global_counterE(%rip)   # arg1, global_counter
    ret
sethrj commented 6 years ago

Could use __attribute__((alias)) to export C++ scoped data to C linkage and directly manipulate it in fortran like:

integer(kind = c_int), &
    bind(c, name='global_ctr') :: global_ctr

Or name could be replaced with the mangled name.

But this doesn't seem portable or worth the effort...

sethrj commented 6 years ago

Unless the global variable is in C scope and can be directly accessed already, I don't think this is much better than calling a set_ or get_ functions wrapped in C.