如何解决如何释放通过 iso_c_binding 调用的函数中分配的内存,然后通过 f2py 传递给 python?
我有以下用 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 或实际程序有关。
解决方法
要获得 type(c_ptr)
指针,可以使用 c_loc()
。相反,loc()
函数是获取一个包含地址的整数 - 可用于 Cray(整数)指针。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。