我正在使用ctypes尝试加快我的代码的速度。
我的问题类似于本教程中的问题:https://cvstuff.wordpress.com/2014/11/27/wraping-c-code-with-python-ctypes-memory-and-pointers/
正如本教程中指出的那样,在使用C函数后,我应该释放内存。这是我的C代码
//C functions
double* getStuff(double *R_list, int items){
double results[items];
double* results_p;
for(int i = 0; i < items; i++){
res = calculation ; \\do some calculation
results[i] = res; }
results_p = results;
printf("C allocated address %p \n", results_p);
return results_p; }
void free_mem(double *a){
printf("freeing address: %p\n", a);
free(a); }
我使用gcc -shared -Wl,-lgsl,-soname, simps -o libsimps.so -fPIC simps.c
进行编译
和python:
//Python
from ctypes import *
import numpy as np
mydll = CDLL("libsimps.so")
mydll.getStuff.restype = POINTER(c_double)
mydll.getStuff.argtypes = [POINTER(c_double),c_int]
mydll.free_mem.restype = None
mydll.free_mem.argtypes = [POINTER(c_double)]
R = np.logspace(np.log10(0.011),1, 100, dtype = float) #input
tracers = c_int(len(R))
R_c = R.ctypes.data_as(POINTER(c_double))
for_list = mydll.getStuff(R_c,tracers)
print 'Python allocated', hex(for_list)
for_list_py = np.array(np.fromiter(for_list, dtype=np.float64, count=len(R)))
mydll.free_mem(for_list)
到最后一行,代码执行了我想要的操作,并且for_list_py
值正确。但是,当我尝试释放内存时,出现分段错误,并且在仔细检查后,与 for_list
-> hex(for_list)
关联的地址与分配给{{1}的地址不同}放在代码的C部分中。
如该问题所指出的,如果
results_p
设置为for_list
,则Python ctypes: how to free memory? Getting invalid pointer error,mydll.getStuff.restype
将返回相同的地址。但是后来我努力将我想要的实际值放入c_void_p
中。这是我尝试过的:
演员(for_list,POINTER(c_double))
for_list_py = np.array(np.fromiter(for_list,dtype = np.float64,count = len(R)))
mydll.free_mem(for_list)
其中的强制转换操作似乎将for_list更改为整数。我对C还是很陌生,非常困惑。我需要释放那块内存吗?如果是这样,我该怎么做,同时又将输出保存在numpy数组中?谢谢!
编辑:看来,在C中分配的地址和我要释放的地址是相同的,尽管我仍然收到分段错误。
for_list_py
如果我C allocated address 0x7ffe559a3960
freeing address: 0x7ffe559a3960
Segmentation fault
会得到print for_list
结论
只是让大家知道,我在使用c_types时有些挣扎。
我最终选择了SWIG而不是c_types。我发现代码总体上运行得更快(与此处提供的版本相比)。我发现这份关于处理SWIG中的内存释放的文档非常有用https://scipy-cookbook.readthedocs.io/items/SWIG_Memory_Deallocation.html,而且SWIG为您提供了一种非常简单的方式处理numpy n维数组的方法。
答案 0 :(得分:1)
退出getStuff
函数后,分配给results
数组的内存不再可用,因此当您尝试释放它时,它将使程序崩溃。
尝试以下方法:
double* getStuff(double *R_list, int items)
{
double* results_p = malloc(sizeof((*results_p) * (items + 1));
if (results_p == NULL)
{
// handle error
}
for(int i = 0; i < items; i++)
{
res = calculation ; \\do some calculation
results_p[i] = res;
}
printf("C allocated address %p \n", results_p);
return results_p;
}