繁体   English   中英

将 numpy 数组保存在 C 结构中

[英]Saving a numpy array in a C structure

我正在使用 ctypes 将 numpy 数组传递给 C 代码。 我想将该信息保存在 C 结构中。 我在 C 中有以下代码:

my_file.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();

my_file.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中的以下内容:

my_file.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;的声明上double ** data; 但是,由于 C 事先不知道 numpy 数组的维度,因此我不知道如何声明此字段。

提前致谢 !

第一个问题: double *data[nb_cols]是一个指针数组,或者等价于一个双指针,但这不是 Python 传递的内容。 Python 正在传递一个 2D 数组,或者等效地一个指向数组的指针,因此您的函数应该采用double (*data)[nb_cols]代替。

第二个问题:C 不允许您在结构中存储指向 VLA 的指针。 您尝试改用双指针,但双指针与指向数组的指针不兼容。 但是,有一个解决方案:由于数组是连续的,因此您可以将指针视为指向第一个元素的指针,然后将其转换为指向使用它的函数中的 VLA 的指针(或手动改为转换索引)。

my_file.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);

my_file.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");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM