python - 在 C 结构中保存一个 numpy 数组
问题描述
我正在使用 ctypes 将 numpy 数组传递给 C 代码。我想将这些信息保存在 C 结构中。我在 C 中有以下代码:
我的文件.h
typedef struct container
{
int nb_rows;
int nb_cols;
double ** data;
};
void save_d2_double(int nb_rows, int nb_cols, double *data[nb_cols]);
void print_container();
我的文件.c
#include <stdio.h>
#include "my_file.h"
struct container c;
void save_d2_double(int nb_rows, int nb_cols, double * data[nb_cols] ){
c.nb_rows = nb_rows;
c.nb_cols = nb_cols;
c.data = data;
}
void print_container(){
printf("\n");
printf("%d\t%d", c.nb_rows, c.nb_cols);
for(int i = 0; i < c.nb_rows; i++){
for(int j = 0; j < c.nb_cols; j++){
printf("%f\t", c.data[i][j]); \\ Error here
}
printf("\n");
}
printf("\n");
}
以及python中的以下内容:
我的文件.py
import numpy as np
import numpy.ctypeslib as npct
import ctypes
LIBC = ctypes.CDLL("my_file.so")
array_2d_double = npct.ndpointer(dtype=np.double, ndim=2)
LIBC.save_d2_double.restype = None
LIBC.save_d2_double.argtypes = [ctypes.c_int, ctypes.c_int, array_2d_double]
LIBC.print_container.restype = None
LIBC.print_container.argtypes = []
# The shape of this array vary in the end application.
x_2d_d = np.array([[1.,2.,3.,10.],[4.,5.,6.,11.],[7.,8.,9.,12.]], dtype=np.float64)
shape = x_2d_d.shape
LIBC.save_d2_double(shape[0], shape[1], x_2d_d)
LIBC.print_container()
当我想访问时,c.data
我得到:
Segmentation fault (core dumped)
我怀疑问题出在声明中double ** data;
,因为 C 事先不知道 numpy 数组的维度,所以我不知道如何声明这个文件。
提前致谢 !
解决方案
第一个问题:double *data[nb_cols]
是一个指针数组,或者等效地是一个双指针,但这不是 Python 传递的。Python 正在传递一个二维数组,或者等效地是一个指向数组的指针,所以你的函数应该double (*data)[nb_cols]
取而代之。
第二个问题:C 不允许您将指向 VLA 的指针存储在结构中。您尝试改用双指针,但双指针与指向数组的指针不兼容。但是,有一个解决方案:由于数组是连续的,您可以将指针视为只是指向第一个元素的指针,然后将其转换为指向您使用它的函数中的 VLA 的指针(或手动而是转换索引)。
我的文件.h:
struct container
{
int nb_rows;
int nb_cols;
double *data;
};
void save_d2_double(int nb_rows, int nb_cols, double *data); /* or double (*data)[nb_cols] */
void print_container(void);
我的文件.c:
#include <stdio.h>
#include "my_file.h"
struct container c;
void save_d2_double(int nb_rows, int nb_cols, double *data) { /* or double (*data)[nb_cols] */
c.nb_rows = nb_rows;
c.nb_cols = nb_cols;
c.data = data;
}
void print_container(void) {
double (*data)[c.nb_cols] = (double (*)[c.nb_cols])c.data; /* optional; see below */
printf("\n");
printf("%d\t%d", c.nb_rows, c.nb_cols);
for(int i = 0; i < c.nb_rows; i++) {
for(int j = 0; j < c.nb_cols; j++) {
printf("%f\t", data[i][j]); /* or c.data[i * c.nb_cols + j] */
}
printf("\n");
}
printf("\n");
}
推荐阅读
- python - 在 lightgbm 中创建正确的标签数据
- c++ - cout 未在控制台上显示字符数组 (char buf) 或 OpenCL HelloWorld 问题中的输出缓冲区
- reactjs - Lodash debounce 不会像预期的那样阻止调度 onChange
- angular - 从表单实现动态查询字符串以处理多个查询
- sql - Laravel:toSql 函数无法正确显示查询
- python - LeetCode 509:斐波那契数“int object not subscriptable”
- angular - 在 Angular 8 中,如果子组件是从代码端附加的,我如何在父组件和子组件之间传递数据?
- mongodb - updateMany 基于 mongodb 中的其他字段
- https - 如何检查到/来自画布元素的查询?
- swagger - OpenApi v3:additionalProperties false 与引用的架构