微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Fortran 中使用 iso_c_binding 接收数组

如何解决如何在 Fortran 中使用 iso_c_binding 接收数组

我正在使用 f2py 封装一个 C 库(稍后在 python/numpy 中使用它们)。在获得帮助 here 使第一个封装工作后,我现在尝试封装更复杂的类型,特别是返回通过 malloc 分配的数组的 C 函数

这是 C 库模型 (c_lib.c):

#include <stdlib.h>

double multiply_numbers(double a,double b);
double *get_array(double a);

double multiply_numbers(double a,double b) {
        return a*b;
}

double *get_array(double a) {
        double *retval;
        int i;

        retval = malloc(100*sizeof(a));

        for(i=0; i<100; i++) {
                retval[i] = i*a;
        }

        return retval;
}

我可以成功封装基本的multiply_numbers函数(f_mod.f90):

module test_c_lib

        use iso_c_binding
        implicit none
        
contains

        subroutine multiply(x,y,z)

                use iso_c_binding

                real(8),intent(in)        :: x
                real(8),intent(in)        :: y
                real(8),intent(out)       :: z
        
                ! Interface to C function
                interface                        
                        real(c_double) function c_multiply_numbers(a,b) bind(C,name="multiply_numbers")
                                import
                                real(c_double),value :: a,b
                        end function
                end interface

                ! Call C function               
                z = c_multiply_numbers(x,y)                

        end subroutine
        
end module

我使用这个 makefile 编译所有东西:

f_mod.so:       f_mod.f90 c_lib.o
                f2py -c f_mod.f90 c_lib.o -m f_mod

c_lib.o:        c_lib.c
                gcc -c -fpic c_lib.c -o c_lib.o

但是我正在努力理解如何编写包装 C 函数 get_array 的子例程。

具体来说,

  • 如何接收 100 件物品的数组?
  • 哪个是接口定义?

注意:我没有尝试任何东西,因为我不知道从哪里开始。

编辑

通过大量的注释,我已经能够封装该函数并使其工作。值得注意的是,f2py 可能需要将 Fortran 指针分配给 Fortran 数组的额外步骤。在这一点上我不确定,但是在尝试直接输出 Fortran 指针时无法编译 f2py。

这是 Fortran 中 f2py 的最终包装子例程:

    subroutine get_array(x,z)

            use iso_c_binding

            real(8),intent(in)        :: x
            real(8),intent(out)       :: z(100)
            
            ! Auxiliary variables to convert C pointer to Fortran Array
            type(c_ptr)                :: ret_c_ptr
            real(8),pointer           :: f_ptr(:)
    
            ! Interface to C function
            interface                        
                    type(c_ptr) function c_get_array(a) bind(C,name="get_array")
                            import
                            real(c_double),value :: a
                    end function
            end interface

            ! Call C function               
            ret_c_ptr = c_get_array(x)                
            call c_f_pointer(ret_c_ptr,f_ptr,[100])
            
            ! Assign Fortran pointer to Fortran output array       
            z = f_ptr

    end subroutine

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。