关于boost.numpy的使用

4 篇文章 0 订阅
2 篇文章 0 订阅

最近的研究中,想使用Python调用C++的编译后的dll。尝试了ctypes,但是发现ctypes对C语言编译的dll兼容性比较好,对C++封装的类就无能为力了。尝试了boost.python,发现它对C++的wrapper比较方便快捷而且不用修改C++已经做好的程序。正当准备使用boost.python大干一场,却发现了指针无法封装的问题。多次Google,证实由于Python没有指针,是没法将C++方法里面的指针形参wrapper成Python可调用的方法。有说可以用引用来实现指针功能的,没有尝试,以后有时间可能会试试。
考虑到我实际传入的是图像数据,在Python中间为ndarray格式,因此我打算将C++的指针形式参数直接改为array格式,然后函数给一个返回值即可。google了一些方法,大多使用boost.numeric来实现,不能直接读取numpy的ndarray格式,看起来比较繁琐就搁一边了。后来在github上找到了boost.numpy的支持,遂大喜,下载并CMake后编译成功,入坑。
编译完doc后,研究了下doc,在此记录下使用方法。

头文件和namespace

#include <boost/numpy.hpp>
#include <iostream>

namespace p = boost::python;
namespace np = boost::numpy;

初始化Python runtime

int main(int argc, char **argv){
  Py_Initialize();
  np::initialize();
}

我是使用Python调用c++的一个类,因此将上面两句直接放在累的构造函数里即可。

dtypes

用Python内建数据类型创建ndarray,需要使用dtypes获取内建Python数据类型,创建一个3x3的ndarray方法如下:

p::tuple shape = p::make_tuple(3, 3);
np::dtype dtype = np::dtype::get_builtin<double>();
np::ndarray a = np::zeros(shape, dtype);

使用python namespace的extract方法来打印输出。首先将其变量转换为string并打印出c++字符:

std::cout << "Original array:\n" << p::extract<char const *>(p::str(a)) << std::endl;

也可以打印dtypes:

std::cout << "Datatype is:\n" << p::extract<char const *>(p::str(a.get_dtype())) << std::endl ;

创建ndarrys

使用tuple创建

p::object tu = p::make_tuple('a','b','c') ;
np::ndarray example_tuple = np::array(tu) ;

使用list创建

p::list l ;
l.append('a') ;
np::ndarray example_list = np::array (l) ;
// 也可指定一个dtype数据类型
np::dtype dt = np::dtype::get_builtin<int>();
np::ndarray example_list1 = np::array (l,dt);

使用数组创建

/**********一维***********/
int data[] = {1,2,3,4,5} ;
// shape:(5,)
p::tuple shape = p::make_tuple(5) ;
// stride:创建ndarray时必须移动并得到下一个元素所需的字节数
// stride:(1,)
p::tuple stride = p::make_tuple(sizeof(int)) ;
// owner用来跟踪传入的数组
p::object own ;
// 创建ndarray
np::ndarray data_ex1 = np::from_data(data,dt, shape,stride,own);
/**********二维***********/
uint8_t mul_data[][4] = {{1,2,3,4},{5,6,7,8},{1,3,5,7}};
shape = p::make_tuple(3,2) ;
stride = p::make_tuple(sizeof(uint8_t)*2,sizeof(uint8_t)) ;
np::dtype dt1 = np::dtype::get_builtin<uint8_t>();
np::ndarray mul_data_ex = np::from_data(mul_data,dt1, p::make_tuple(3,4),p::make_tuple(4,1),p::object());

注意的问题:

  • 此方法创建的ndarray数据保存区仍然为上面的数组,不能将该数组删除。
  • shape和stride的shape必须一样,也就是说shape有几个维度就需要几个stride。

使用ndarrys

int arr[] = {1,2,3,4,5} ;
np::ndarray py_array = np::from_data(arr, np::dtype::get_builtin<int>() , p::make_tuple(5), p::make_tuple(sizeof(int)), p::object());
// print
std::cout << "C++ array :" << std::endl ;
for (int j=0;j<4;j++){
  std::cout << arr[j] << ' ' ;
}
std::cout << std::endl << "Python ndarray :" << p::extract<char const *>(p::str(py_array)) << std::endl;
// 访问并修改py_array,比较两者打印结果是否一致
py_array[1] = 5 ;
std::cout << "Is the change reflected in the C++ array used to create the ndarray ? " << std::endl ;
for (int j = 0; j < 5; j++){
  std::cout << arr[j] << ' ' ;
}
// 修改原c++数组,比较两者打印结果是否一致
arr[2] = 8 ;
std::cout << std::endl << "Is the change reflected in the Python ndarray ?" << std::endl << p::extract<char const *>(p::str(py_array)) << std::endl;

boost.numpy定义

我用的时候上面方法访问ndarray的方法不够方便,因此我查阅了其定义,发现可以使用 char * get_data() const;方法直接获取数据区域的指针,直接访问数据就方便多了。
另外boost.numpy定义如下:

namespace boost{

    namespace numpy{

    class ndarray : public python::object{

    public:
          enum bitflag
          {
            NONE=0x0, C_CONTIGUOUS=0x1, F_CONTIGUOUS=0x2, V_CONTIGUOUS=0x1|0x2,
            ALIGNED=0x4, WRITEABLE=0x8, BEHAVED=0x4|0x8,
            CARRAY_RO=0x1|0x4, CARRAY=0x1|0x4|0x8, CARRAY_MIS=0x1|0x8,
            FARRAY_RO=0x2|0x4, FARRAY=0x2|0x4|0x8, FARRAY_MIS=0x2|0x8,
            UPDATE_ALL=0x1|0x2|0x4, VARRAY=0x1|0x2|0x8, ALL=0x1|0x2|0x4|0x8
          };

          ndarray view(dtype const & dt) const;
          ndarray astype(dtype const & dt) const;
          ndarray copy() const;
          int const shape(int n) const;
          int const strides(int n) const;
          char * get_data() const;
          dtype get_dtype() const;
          python::object get_base() const;
          void set_base(object const & base);
          Py_intptr_t const * get_shape() const;
          Py_intptr_t const * get_strides() const;
          int const get_nd() const;

          bitflag const get_flags() const;

          ndarray transpose() const;
          ndarray squeeze() const;
          ndarray reshape(python::tuple const & shape) const;
          python::object scalarize() const;
    };

    ndarray zeros(python::tuple const & shape, dtype const & dt);
    ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt);

    ndarray empty(python::tuple const & shape, dtype const & dt);
    ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);

    ndarray array(python::object const & obj);
    ndarray array(python::object const & obj, dtype const & dt);

    template <typename Container>ndarray from_data(void * data,dtype const & dt,Container shape,Container strides,python::object const & owner);
    template <typename Container>ndarray from_data(void const * data, dtype const & dt, Container shape, Container strides, python::object const & owner);

    ndarray from_object(python::object const & obj, dtype const & dt,int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
    ndarray from_object(python::object const & obj, dtype const & dt,int nd, ndarray::bitflag flags=ndarray::NONE);
    ndarray from_object(python::object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE);
    ndarray from_object(python::object const & obj, int nd_min, int nd_max,ndarray::bitflag flags=ndarray::NONE);
    ndarray from_object(python::object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE);
    ndarray from_object(python::object const & obj, ndarray::bitflag flags=ndarray::NONE);

    ndarray::bitflag operator|(ndarray::bitflag a, ndarray::bitflag b);
    ndarray::bitflag operator&(ndarray::bitflag a, ndarray::bitflag b);

}

ufunc

暂时不用,没有研究。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值