【发布时间】:2021-07-24 10:49:08
【问题描述】:
我有以下用 C 语言编写的测试库,一个函数分配一个数组,另一个函数用于释放该内存。请注意,返回的数组作为指向指针的指针传递,因为在实际应用程序中我需要返回多个数组的函数:
#include <stdlib.h>
#include <stdio.h>
void return_array(int length, int **myarray);
void free_array(void *myarray);
void return_array(int length, int **myarray) {
int i;
*myarray = malloc(length*sizeof(int));
for(i=0; i<length; i++) {
(*myarray)[i] = i+1;
}
}
void free_array(void *myarray) {
free(myarray);
}
以及使用iso_c_binding和f2py的相应包装器:
module test_c_lib
use iso_c_binding
implicit none
contains
subroutine return_array(l, z)
use iso_c_binding
integer, intent(in) :: l
integer, intent(out) :: z(l)
type(c_ptr) :: ret_c_ptr
integer, pointer :: f_ptr(:)
interface
subroutine c_return_array(c_l, c_z) bind(C, name="return_array")
import
integer(c_int),value :: c_l
type(c_ptr) :: c_z(*)
end subroutine
end interface
call c_return_array(10, ret_c_ptr)
call c_f_pointer(ret_c_ptr, f_ptr, [l])
z = f_ptr
end subroutine
subroutine free_integer_array(z)
use iso_c_binding
integer, pointer :: z(:)
type(c_ptr) :: c_z
interface
subroutine c_free_array(c_array) bind (C, name="free_array")
import
type(c_ptr) :: c_array(*)
end subroutine
end interface
c_z = loc(z)
call c_free_array(c_z)
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
但我明白了:
xxx | c_z = loc(z)
| 1
Error: Cannot convert INTEGER(8) to TYPE(c_ptr) at (1)
这两个例程的构建方式可能存在更多问题或不良做法,但上面的代码是我尝试过的。
- 这两个步骤暴露的 C 函数将如何实现?
- 对于每种类型的数组(整数、实数等),我是否需要一个 Fortran 中的免费例程?
- 在 Fortran 中
type(c_ptr) :: c_z(*)是在 C 中指定int **myarray的正确方法吗?
我在 FreeBSD12 中使用 gfortran。
编辑
根据 Vladimir 的回答,我重新编码 free_integer_array 并合并了两个更改:
subroutine free_integer_array(z)
use iso_c_binding
integer, pointer :: z
type(c_ptr) :: c_z
interface
subroutine c_free_array(c_array) bind (C, name="free_array")
import
type(c_ptr) :: c_array(*)
end subroutine
end interface
c_z = c_loc(z)
call c_free_array(c_z)
end subroutine
然后我使用f2py生成的库如下:
>>> import f_mod
>>> a = f_mod.test_c_lib.return_array(10)
>>> a
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=int32)
到目前为止一切顺利,返回了一个 numpy 数组。然后我想释放它:
>>> free_integer_array(a)
这里的内核在一段时间后就死了,除了[Errno 79] Inappropriate file type or format,Jupyter Notebook 日志中没有其他信息,但甚至不确定这与 Jupyter Notebook 或实际程序有关。
【问题讨论】:
标签: fortran gfortran f2py fortran-iso-c-binding