c++ - 将 C++ std::Vector 传递给 Python 中的 numpy 数组

标签 c++ arrays vector numpy

我正在尝试将我在 C++ 代码中生成的 double vector 传递给 python numpy 数组。我希望在 Python 中进行一些下游处理,并希望在填充 numpy 数组后使用一些 python 工具。我想做的最重要的事情之一就是能够绘制事物,而 C++ 在这方面有点笨拙。我还希望能够利用 Python 的统计能力。

虽然我不太清楚如何做到这一点。我花了很多时间浏览 Python C API 文档。我遇到了一个显然可以解决问题的函数 PyArray_SimpleNewFromData。就代码的整体设置而言,我仍然很不清楚。我正在构建一些非常简单的测试用例来帮助我理解这个过程。我在 Visual Studio express 2012 中生成了以下代码作为独立的 Empty 项目。我将此文件称为 Project1

#include <Python.h>
#include "C:/Python27/Lib/site-packages/numpy/core/include/numpy/arrayobject.h"

PyObject * testCreatArray()
{
    float fArray[5] = {0,1,2,3,4};
    npy_intp m = 5;
    PyObject * c = PyArray_SimpleNewFromData(1,&m,PyArray_FLOAT,fArray);
    return c; 
}

我的目标是能够在 Python 中读取 PyObject。我被卡住了,因为我不知道如何在 Python 中引用这个模块。特别是如何从 Python 导入此项目,我尝试从 python 中的项目路径导入 Project1,但失败了。一旦我理解了这个基本情况,我的目标就是想办​​法将我在主函数中计算的 vector 容器传递给 Python。我也不知道该怎么做。

任何可以帮助我解决这个问题的专家,或者发布一个包含一些代码的简单示例,该示例从一个简单的 c++ vector 读取并填充一个 numpy 数组,我将不胜感激。非常感谢。

最佳答案

我不是 cpp-hero,但想为我的解决方案提供 1D 和 2D vector 的两个模板函数。这是使用 l8ter 的单行代码,通过模板化 1D 和 2D vector ,编译器可以为您的 vector 形状采用正确的版本。在 2D 的情况下,如果形状不规则,则抛出一个字符串。 例程在此处复制数据,但可以轻松修改它以获取输入 vector 的第一个元素的地址,以使其只是一个“表示”。

用法如下:

// Random data
vector<float> some_vector_1D(3,1.f); // 3 entries set to 1
vector< vector<float> > some_vector_2D(3,vector<float>(3,1.f)); // 3 subvectors with 1

// Convert vectors to numpy arrays
PyObject* np_vec_1D = (PyObject*) vector_to_nparray(some_vector_1D);
PyObject* np_vec_2D = (PyObject*) vector_to_nparray(some_vector_2D);

您还可以通过可选参数更改 numpy 数组的类型。模板函数有:

/** Convert a c++ 2D vector into a numpy array
 *
 * @param const vector< vector<T> >& vec : 2D vector data
 * @return PyArrayObject* array : converted numpy array
 *
 * Transforms an arbitrary 2D C++ vector into a numpy array. Throws in case of
 * unregular shape. The array may contain empty columns or something else, as
 * long as it's shape is square.
 *
 * Warning this routine makes a copy of the memory!
 */
template<typename T>
static PyArrayObject* vector_to_nparray(const vector< vector<T> >& vec, int type_num = PyArray_FLOAT){

   // rows not empty
   if( !vec.empty() ){

      // column not empty
      if( !vec[0].empty() ){

        size_t nRows = vec.size();
        size_t nCols = vec[0].size();
        npy_intp dims[2] = {nRows, nCols};
        PyArrayObject* vec_array = (PyArrayObject *) PyArray_SimpleNew(2, dims, type_num);

        T *vec_array_pointer = (T*) PyArray_DATA(vec_array);

        // copy vector line by line ... maybe could be done at one
        for (size_t iRow=0; iRow < vec.size(); ++iRow){

          if( vec[iRow].size() != nCols){
             Py_DECREF(vec_array); // delete
             throw(string("Can not convert vector<vector<T>> to np.array, since c++ matrix shape is not uniform."));
          }

          copy(vec[iRow].begin(),vec[iRow].end(),vec_array_pointer+iRow*nCols);
        }

        return vec_array;

     // Empty columns
     } else {
        npy_intp dims[2] = {vec.size(), 0};
        return (PyArrayObject*) PyArray_ZEROS(2, dims, PyArray_FLOAT, 0);
     }


   // no data at all
   } else {
      npy_intp dims[2] = {0, 0};
      return (PyArrayObject*) PyArray_ZEROS(2, dims, PyArray_FLOAT, 0);
   }

}


/** Convert a c++ vector into a numpy array
 *
 * @param const vector<T>& vec : 1D vector data
 * @return PyArrayObject* array : converted numpy array
 *
 * Transforms an arbitrary C++ vector into a numpy array. Throws in case of
 * unregular shape. The array may contain empty columns or something else, as
 * long as it's shape is square.
 *
 * Warning this routine makes a copy of the memory!
 */
template<typename T>
static PyArrayObject* vector_to_nparray(const vector<T>& vec, int type_num = PyArray_FLOAT){

   // rows not empty
   if( !vec.empty() ){

       size_t nRows = vec.size();
       npy_intp dims[1] = {nRows};

       PyArrayObject* vec_array = (PyArrayObject *) PyArray_SimpleNew(1, dims, type_num);
       T *vec_array_pointer = (T*) PyArray_DATA(vec_array);

       copy(vec.begin(),vec.end(),vec_array_pointer);
       return vec_array;

   // no data at all
   } else {
      npy_intp dims[1] = {0};
      return (PyArrayObject*) PyArray_ZEROS(1, dims, PyArray_FLOAT, 0);
   }

}

关于c++ - 将 C++ std::Vector 传递给 Python 中的 numpy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18780570/

相关文章:

c++ - 将非静态函数指针传递给另一个类?

javascript - 在 javascript 中从平面对象数组构建对象图

c++ - 计算容器内的项目重复次数

c++ - IncrediBuild - 错误 : First character of string should be '0' or '1'

c++ - 为什么我在 visual studio 2010 中运行代码后得到 4 作为输出

c++ - 如何将字符串转换为带符号的 float ?

php - 使用 PHP MySQL 创建嵌套的 JSON

javascript - 从数组中生成一个随机单词,然后将其打印到控制台日志中的 javascript 函数中

c++ - 按偶数和奇数索引对 vector 进行排序。 C++

c++ - std::vector 的概念和 GCC 实现