ctypes:初始化数组并传递给C函数

ctypes: Initialize array of arrays and pass to C function

本文关键字:函数 初始化 数组 ctypes      更新时间:2023-10-16

我一直在摆弄ctypes,遇到了两个问题:

问题1.我想使用double*数组构建cellComplex,但我希望new_cellComplex接受double*的数组(以及size_t参数),而不是固定数量的double*。对于一个固定的数字,代码看起来像这样(并且运行良好)

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代码:

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)

我宁愿有以下(哪些分段故障)

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代码:

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中处理它。记录在案,我非常感谢这个堆叠式的答案,在那里我学会了这样的魔法——但只要它在我的代码中,我晚上就睡不着了。。。

使用double [][2]而不是double **。您正在传递一个连续的C数组,您希望将其作为指向一行2项的指针进行访问。第一个索引是行索引。

将数组声明为double **是指向double指针的指针,因此p[i]是指针,p[i][0]再次取消引用它。但根据您的数据,p[i]是一个偶然的NULL指针。

请参阅comp.lang.cFAQ,问题6.18:当我将一个二维数组传递给一个函数时,我的编译器抱怨道指向指针的指针。

对于返回类型,您可以使用c_void_p的子类,或者根据ctypes文档中第15.17.1.7节的最后一段使用钩子from_param_as_parameter_