【发布时间】:2012-06-18 21:29:56
【问题描述】:
我正在尝试使用 Python Ctypes 来连接已发布的(封闭源代码)C++ 库。我(尝试过)编写了一个基本的 C 样式函数包装器来构造 C++ 矢量样式对象并调用 C++ 例程。我还(尝试过)编写了一个基本的 python 脚本来加载共享库。一切正常,除了调用 C++ 例程的行,它产生:
*** glibc detected *** python: free(): invalid next size (fast): 0x0000000001e73c00 ***
这里是文件,不幸的是我不能分享标题,但如果需要的话我可以写一些类似的东西......
gaumixmod.cpp:
#include "nr3.h"
#include "cholesky.h"
#include "gaumixmod.h"
extern "C" {
void cGaumixmod(double* D, int Dm, int Dn, double* M, int Mm, int Mn) {
MatDoub ddata(Dm,Dn,*D); // construct Matrix (vector) type
MatDoub mmeans(Mm,Mn,*M); // construct Matrix (vector) type
//XXX test numpy array is coming through as C array and we can rw, checks OK
int i;
// for(i=0;i<Dn*Dm;++i) {
// printf("Address %x : ",(D+i));
// printf("was %f \t" , D[i]);
// D[i]+=1.0;
// printf("now: %f \n" , D[i]);
// }
// check that array D was copied to matrix ddata, and we can r/w
for(i=0;i<Dm*Dn;++i) {
printf("iter %d Address %x : ",i,ddata[i/Dm][i%Dm]);
printf("was %f \t" , ddata[i/Dm][i%Dm]);
ddata[i/Dm][i%Dm]+=1.0;
printf("now: %f \n" ,ddata[i/Dm][i%Dm]);
}
Gaumixmod::Gaumixmod(ddata,mmeans);
//return data from vector to ctypes array C so we can check data returns to python
//via numpy array, checks ok
for(i=0;i<Dm*Dn;++i) {
D[i] = ddata[i/Dm][i%Dm];
}
}
}
goumixmod.py:
import platform,ctypes
import numpy as np
# ------------------------------------------------------------------------
# define correct library from platfrom, assuming 64bit for linux machines
# ------------------------------------------------------------------------
if platform.system()=='Microsoft':
raise Exception('MS not supported.')
elif platform.system()=='Darwin':
libgaumixmod = ctypes.cdll.LoadLibrary("./gaumixmod.so")
elif platform.system()=='Linux':
libgaumixmod = ctypes.cdll.LoadLibrary("./gaumixmod.so")
else:
#hope for the best
libgaumixmod = ctypes.cdll.LoadLibrary("./gaumixmod.so")
# --------------------------------------------------
# define SafeCall
#---------------------------------------------------
def SafeCall(ret):
"""pass, code l8r""
print ret
#---------------------------------------------------
# define arg types and res types of function
# -----------------------------------------------------------------------
_gaumixmod = libgaumixmod.cGaumixmod
_gaumixmod.restype = ctypes.c_int
_gaumixmod.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64,flags='C_CONTIGUOUS'),
ctypes.c_int,
ctypes.c_int,
np.ctypeslib.ndpointer(dtype=np.float64,flags='C_CONTIGUOUS'),
ctypes.c_int,
ctypes.c_int]
def gaumixmod(D,K):
"""Python binding for C++ guassian mixure model code."""
ret = _gaumixmod(D,D.shape[0],D.shape[1],K,K.shape[0],K.shape[1])
SafeCall(ret)
return D,K
D = np.ones((100,100)).astype(np.float64)
K = np.ones((4,1)).astype(np.float64)
print gaumixmod(D,K)
我编译这首爵士乐:
g++ -fPIC -c gaumixmod.cpp;
g++ -shared -o gaumixmod.so gaumixmod.o
然后运行
python gaumixmod.py
我的研究表明此错误类似于 segFault,其中 python 试图访问其范围之外的内存...这是我不明白的部分,因为注释掉 C++ 行 Gaumixmod::Gaumixmod() ,一切正常,并且该例程应该在 cGaumixmod() 函数中实例化的向量上运行,而不是 python numpy 数组。我对 C++ 真的很陌生,虽然我已经多次将 C 类型用于 C 库。我希望有一些 C++、python 和 ctypes 经验的人可以在这里提供一些见解/指导。
谢谢!
【问题讨论】:
-
看看你的 _gaumixmod.argtypes 行。 np.ctypeslib.ndpointer(dtype=np.float64,flags='C_CONTIGUOUS') 真的是一种类型吗?为了确定,我会尝试 ctypes.POINTER(ctypes.c_double) 。由于 'C_CONTIGUOUS' 与指针类型无关,因为它只是指向内存中的一个位置。
-
另一件事可能更有可能。 _gaumixmod(D, ...) 正在寻找一个 double* 并且您正在给它一个 np.array。如果没有别的,它应该是 D.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
-
你考虑过使用 Cython 吗?
-
@K.Brafford,好建议。这比尝试使用 ctypes 更不容易出错。
标签: c++ python c segmentation-fault ctypes