ctypes: Initialize array of arrays and pass to C function
我一直在玩 ctypes,遇到了两个问题:
问题 1. 我想使用 double* 数组构建一个 cellComplex,但我希望 new_cellComplex 接受一个 double*// 的数组(以及一个 size_t 参数),而不是一个固定数量的 double*//’s。使用固定数字,代码看起来像这样(并且运行良好):
1 2 3 4 5 6 7 8 9 10 11
|
extern"C" {
void * new_cellComplex (double* p_x, double* p_y, double* p_z ) {
std::vector< std::pair<double,double> > point; point.push_back( std::make_pair(p_x[0],p_x[1])); point.push_back( std::make_pair(p_x[0],p_x[1])); point.push_back( std::make_pair(p_x[0],p_x[1]));
cellComplex<double>* cmplx = new cellComplex<double>(point); return cmplx; } |
使用 Python 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
import ctypes
cellComplex_lib = ctypes.cdll.LoadLibrary(‘./cellComplex_lib.so’) cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p cellComplex_lib.new_cellComplex.argtypes = [ctypes.c_double*2, ctypes.c_double*2, ctypes.c_double*2]
p_x = (ctypes.c_double*2)(0.0,1.0) p_y = (ctypes.c_double*2)(0.0,1.0) p_z = (ctypes.c_double*2)(0.0,1.0)
cmplx = cellComplex_lib.new_cellComplex(p_x,p_y,p_z) |
我宁愿有以下(段错误):
1 2 3 4 5 6 7 8 9 10 11
|
extern"C" {
void * new_cellComplex (double** p, size_t dim ) {
std::vector< std::pair<double,double> > point; for (size_t i=0; i<dim; ++i) { point.push_back( std::make_pair(p[i][0],p[i][1])); } cellComplex<double>* cmplx = new cellComplex<double>(point); return cmplx; } } |
使用 Python 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
import ctypes
dim = 3 cellComplex_lib = ctypes.cdll.LoadLibrary(‘./cellComplex_lib.so’) cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p cellComplex_lib.new_cellComplex.argtypes = [(ctypes.c_double*2)*dim, ctypes.c_size_t]
p_x = (ctypes.c_double*2)(0.0,1.0) p_y = (ctypes.c_double*2)(0.0,1.0) p_z = (ctypes.c_double*2)(0.0,1.0)
p = ((ctypes.c_double*2)*dim)(p_x,p_y,p_z)
cmplx = cellComplex_lib.new_cellComplex(p,dim) |
^这不起作用,我不知道为什么。
问题 2。(包括在此处是因为它在问题 1 中很明显)我正在从我的 C 代码返回一个本质上匿名的指针!这只是感觉,嗯,很脏,并且必须有更好的方法来返回自定义数据类型并在 Python 中处理它。作为记录,我非常感谢这个 stackoverflow 的答案,我在其中学到了这样的巫术 – 但只要它在我的代码中,我就无法在晚上睡觉……
使用 double [][2] 代替 double **。您正在传递一个连续的 C 数组,您希望将其作为指向一行 2 项的指针进行访问。第一个索引是行索引。
将数组声明为 double ** 是指向 double 指针的指针,因此 p[i] 是指针,而 p[i][0] 再次取消引用它。但是根据您的数据, p[i] 是一个 NULL 指针。
Refer to the comp.lang.c FAQ, question
6.18: My compiler complained when I passed a two-dimensional array to a function expecting a
pointer to a pointer.
对于返回类型,您可以继承 c_void_p,或者使用 ctypes 文档中第 15.17.1.7 节最后一段的钩子 from_param 和 _as_parameter_。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/268044.html