首页 > 解决方案 > 将 ndarray 从 Python 扩展返回到 C

问题描述

我有一个 C 程序,我从中调用 Python 函数。我希望这个 Python 函数返回一个 ndarray,然后我可以在我的 C 代码中使用它。我需要一个 ndarray,因为我想要 Python 代码记录声音并使用 sounddevice.record() 将数组发送回 C 代码。目前我使用 PyArrayObject* 作为我接收的变量类型(pValue)。但我在输出中得到的只是零。我已经尝试过这个程序来接收整数并且这确实有效,所以它特别是传递数组的问题所在。

C代码

#include <stdio.h>
#include <Python.h>
#include <numpy/ndarrayobject.h>

int main(){
      PyObject *pName, *pModule, *pFunc;
      PyArrayObject *pValue;
      Py_Initialize();
      import_array();

      pName = PyString_FromString("audioPipe");
      pModule = PyImport_Import(pName);
      Py_DECREF(pName);

      if(pModule == NULL) printf("its null\n");
      if (pModule != NULL) {
          pFunc = PyObject_GetAttrString(pModule, "recordSound");        

          if (pFunc && PyCallable_Check(pFunc)) {
            pValue = PyObject_CallObject(pFunc, NULL);
            for(int r = 0; r < 10; r++){printf("%f\n", pValue[r]);}
            if (pValue == NULL) {
              Py_DECREF(pFunc);
              Py_DECREF(pModule);
              PyErr_Print();
              fprintf(stderr,"Call failed\n");
              return 1;
            }
          }
          else {
              if (PyErr_Occurred())
                  PyErr_Print();
              fprintf(stderr, "Cannot find function \n");
          }
          Py_XDECREF(pFunc);
          Py_DECREF(pModule);
        }
        else {
            PyErr_Print();
            fprintf(stderr, "Failed to load \\n");
            return 1;
        }
        Py_Finalize();
        return 0;
}

Python 代码(在文件 audioPipe.py 中)

import sounddevice as sd
fs = 44100
channels = 2

def recordSound():
    recArray = np.arange(20)
    print recArray
    print type(recArray)
    return recArray

输出

PYTHONPATH=. ./audioPassing
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]
<type 'numpy.ndarray'>
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000

标签: pythoncmultidimensional-arraynumpy-ndarraycpython

解决方案


我终于找到了一种使用数组的方法。我将它转换为 npy_float** 类型。(二维,我的应用程序所必需的)使用 PyArray_AsCarray() 函数。从那时起,您就可以使用它了。更大的问题主要出在我的打印声明上。我使用了错误的格式,导致它被读取错误。另一个重要的注意事项是,要使用 PyArray_AsCArray 函数,您应该使用 PyArray_Descr* 而不是 typenum。否则你会得到一个分段错误。

PyArray_Descr *descr;
descr = PyArray_DescrFromType(PyArray_TYPE(pValue));

if (PyArray_AsCArray(&pValue, (void*)&array, PyArray_DIMS(pValue), PyArray_NDIM(pValue), descr) < 0)  {
   PyErr_SetString(PyExc_TypeError, "error converting to c array");
   return NULL;
}

重要的是,如果你想打印出来,你需要使用格式。

printf("datapoint: %"NPY_FLOAT_FMT"\n", array[][]);

推荐阅读