[英]ctypes: Initialize array of arrays and pass to C function
I've been fooling with ctypes and have come across two problems: 我一直在愚弄ctypes并遇到两个问题:
Problem 1. I would like to build a cellComplex
using double*
arrays, but I want new_cellComplex
to accept an array of double*
's (along with a size_t
argument) rather than a fixed number of double*
's. 问题1.我想建立一个cellComplex
使用double*
阵列,但我想new_cellComplex
接受的阵列double*
的(具有沿size_t
参数),而不是一个固定数量的double*
的。 With a fixed number the code looks like this (and it runs fine) : 使用固定的数字,代码如下所示(并且运行良好) :
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;
}
with Python code: 使用Python代码:
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)
I would rather have the following (which segfaults) : 我宁愿有以下内容(segfaults) :
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;
}
}
With Python code: 使用Python代码:
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)
^This doesn't work and I don't know why. ^这不起作用,我也不知道为什么。
Problem 2. (Included here because it's glaring in Problem 1 ) I am returning an essentially anonymous pointer from my C
code! 问题2。 (包含在这里,因为它在问题1中很刺眼 )我正在从我的C
代码中返回一个本质上是匿名的指针! This just feels, well, dirty, and there must be a better way to return a custom data type and deal with it back in Python. 感觉很好,很脏,必须有更好的方法来返回自定义数据类型并用Python处理。 For the record, I am extremely grateful for this stackoverflow answer where I learned such sorcery - but I'm not going to be able to sleep at night as long as it's in my code... 记录下来,我非常感谢我在这里学到了这样的法术的stackoverflow答案 -但只要在我的代码中,我就无法在晚上入睡...
Instead of double **
, use double [][2]
. 代替double **
,请使用double [][2]
。 You're passing a contiguous C array that you want to access as a pointer to a row of 2 items. 您正在传递要访问的连续C数组,作为指向2个项目的行的指针。 The first index is the row index. 第一个索引是行索引。
Declaring the array as a double **
is a pointer to a double
pointer, so p[i]
is a pointer, and p[i][0]
dereferences it again. 将数组声明为double **
是指向double
指针的指针,因此p[i]
是指针,而p[i][0]
再次取消引用它。 But p[i]
is a NULL
pointer by chance according to your data. 但是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. 请参阅comp.lang.c常见问题, 问题6.18 :当我将二维数组传递给需要指针的函数时,编译器抱怨。
For the return type, you can subclass c_void_p
, or use the hooks from_param
and _as_parameter_
per the last paragraph of section 15.17.1.7 in the ctypes docs. 对于返回类型,可以将c_void_p
子类c_void_p
,或者在ctypes文档中第15.17.1.7节的最后一段中使用钩子from_param
和_as_parameter_
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.