Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:从ctypes外部函数成功返回后内存损坏_Python_C_Numpy_Ctypes - Fatal编程技术网

Python:从ctypes外部函数成功返回后内存损坏

Python:从ctypes外部函数成功返回后内存损坏,python,c,numpy,ctypes,Python,C,Numpy,Ctypes,非必要背景:我在ctypes指针方面遇到了很多问题,到目前为止,我已经能够解决这些问题,方法是在Python端将所有内容剥离为c\u void\p,然后通过重铸和指针算法挖掘出我在c中需要的内容。然而,我终于在Python中遇到了一个我无法解决的问题,我希望sage对这个MWE的回答能让我修复所有其他的黑客 MWE:在下面两种情况下,我都成功地从一个简单的C外部函数定义、填充、传递和返回了一个struct from/to Python。在第一种情况下(ff1.py),一切正常。在第二种情况下(f

非必要背景:我在
ctypes
指针方面遇到了很多问题,到目前为止,我已经能够解决这些问题,方法是在Python端将所有内容剥离为
c\u void\p
,然后通过重铸和指针算法挖掘出我在c中需要的内容。然而,我终于在Python中遇到了一个我无法解决的问题,我希望sage对这个MWE的回答能让我修复所有其他的黑客

MWE:在下面两种情况下,我都成功地从一个简单的C外部函数定义、填充、传递和返回了一个struct from/to Python。在第一种情况下(
ff1.py
),一切正常。在第二种情况下(
ff2.py
),函数返回并成功地在Python中取消引用,然后Python崩溃。这两种情况之间的区别在于,从Python传递出来的结构是作为模块中的变量导入的,还是在传递给C之前从Python函数返回的

ff.h

struct-dummy
{
int-dim1;
int-dim2;
双*阵列ptr;
};
无效的
外部函数(结构虚拟*ptr虚拟到虚拟);
ff.c

#包括“ff.h”
__属性(可见性(“默认”))
无效的
外部函数(结构虚拟*d_ptr)
{
常数int N=d_ptr->dim1;
常量int M=d_ptr->dim2;

对于(int i=0;i一个指向数组数据的ctypes指针不能使数组保持活动状态。您可以通过
dela
使第一个指针崩溃


为结构创建一个包装器,该包装器还通过保存对numpy数组的引用来保持该数组的活动状态。

@antti haapala确实如此!以下是我的工作版本:

struct\u w\u wrapper.py

将numpy导入为np
导入ctypes
类虚拟结构类型(ctypes.Structure):
_字段\=[('dim1',ctypes.c_int),
(“dim2”,ctypes.c_int),
('array_ptr',ctypes.POINTER(ctypes.c_double))]
##
##包装纸
##这些论据显然是根据实际情况量身定做的
##伪结构类型,不是任意类型
##“要包装的结构”
##
def不释放我(要包装的结构):
类包装器:
定义初始值(自身、dim1、dim2、arr):
self.dim1=dim1##这两个整数应该保持不变
self.dim2=dim2###不带包装,但不管怎样
self.arr=arr
self.struct=\
要包装的结构(ctypes.c_int(dim1),
c类型c_int(dim2),
arr.ctypes.data_as(
ctypes.POINTER(
ctypes.c_double)))
定义结构(自身):
返回self.struct
返回包装器
包装的虚拟结构类型=不释放(虚拟结构类型)
def make_实例(n,m):
a=np.one((n,m),dtype=ctypes.c\u double,order='c')
返回包装的\u伪\u结构\u类型(n,m,a)
ff3.py

将numpy导入为np
导入ctypes
导入操作系统
从struct_w_wrapper import dummy_struct_type,生成_实例
fflib=ctypes.CDLL(os.path.abspath('ff_lib.so'))
fflib.foreign\u func.argtypes=[ctypes.POINTER(伪结构类型)]
fflib.foreign_func.restype=无
包装的虚拟结构实例=生成实例(12,50)
dummy\u struct\u instance=wrapped\u dummy\u struct\u instance
fflib.foreign函数(ctypes.byref(伪结构实例))
打印(虚拟结构实例数组ptr[19])
然后,从提示符:

$ python3 ff3.py 
3.14159
更新:我现在知道这是Python ctypes中的一个古老的已知特性(),它有一个内置的解决方法。有一个
data
方法,它反映了这个SO问题中有问题的
data\u as
行为;还有numpy自己的
data\u as
方法,其中包含我们想要的:“返回的指针将保留对数组的引用。”

由于我的问题导致崩溃,我启动了一个Python bug(),如果您对实现自己的解决方案感兴趣,可以对它进行一些很好的讨论

$ python3 ff3.py 
3.14159