将 boost::python::numpy::ndarray 作为 boost::python 函数的(默认与否)参数传递?

Posted

技术标签:

【中文标题】将 boost::python::numpy::ndarray 作为 boost::python 函数的(默认与否)参数传递?【英文标题】:Passing boost::python::numpy::ndarray as (default or not) argument of a boost::python function? 【发布时间】:2020-01-11 10:45:42 【问题描述】:

是否可以将 boost::python::numpy::ndarray 作为 boost::python 函数的(默认或不)参数传递?

dummy 没有 ndarray。愚蠢的一个 ndarray 参数,但没有默认值。 silly 有一个 ndarray 作为默认值。

>> more dummy.cpp stupid.cpp silly.cpp 
::::::::::::::
dummy.cpp
::::::::::::::
#include <boost/python.hpp>
namespace bp = boost::python;

int f(double x, double y=1.0) return (int)(x+y);;

BOOST_PYTHON_MODULE(dummy)

  bp::def("f", f, ( bp::arg("x"), bp::arg("y")=1.0 ) );

::::::::::::::
stupid.cpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, double y=1.0) return (int)(x.shape(0)+y);;

BOOST_PYTHON_MODULE(stupid)

  bp::def("f", f, ( bp::arg("x"), bp::arg("y")=1.0 ) );

::::::::::::::
silly.cpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, np::ndarray * y=nullptr) return (int)(y ? x.shape(0)+y->shape(0) : x.shape(0));;

BOOST_PYTHON_MODULE(silly)

  bp::def("f", f, ( bp::arg("x"), bp::arg("y")=nullptr ) );


>> make
g++ -I /usr/include/python2.7 -o dummy.so  -fPIC -shared dummy.cpp  -lboost_python -lboost_numpy -lpython2.7
g++ -I /usr/include/python2.7 -o stupid.so -fPIC -shared stupid.cpp -lboost_python -lboost_numpy -lpython2.7
g++ -I /usr/include/python2.7 -o silly.so  -fPIC -shared silly.cpp  -lboost_python -lboost_numpy -lpython2.7

>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22) 
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummy; dummy.f(1)
2
>>> import numpy; import stupid; stupid.f(numpy.array([1, 2, 3])) 
Segmentation fault

更新

尝试在f 中添加Py_Initialize(); np::initialize(); 没有成功

>> more stupid.cpp silly.cpp 
::::::::::::::
stupid.cpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, double y=1.0) 
  Py_Initialize();
  np::initialize();
  return (int)(x.shape(0)+y);
;

BOOST_PYTHON_MODULE(stupid)

  bp::def("f", f, ( bp::arg("x"), bp::arg("y")=1.0 ) );

::::::::::::::
silly.cpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, np::ndarray * y=nullptr) 
  Py_Initialize();
  np::initialize();
  return (int)(y ? x.shape(0)+y->shape(0) : x.shape(0));
;

BOOST_PYTHON_MODULE(silly)

  bp::def("f", f, ( bp::arg("x"), bp::arg("y")=nullptr ) );


>> make
g++ -I /usr/include/python2.7 -o stupid.so -fPIC -shared stupid.cpp -lboost_python -lboost_numpy -lpython2.7
g++ -I /usr/include/python2.7 -o silly.so  -fPIC -shared silly.cpp  -lboost_python -lboost_numpy -lpython2.7

>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22) 
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy; import stupid; stupid.f(numpy.array([1, 2, 3]))
Segmentation fault

更新

好的,让它与调用 in BOOST_PYTHON_MODULE 一起工作。仍然使用默认参数 KO(silly 示例)。

>> more stupid.cpp silly.cpp 
::::::::::::::
stupid.cpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, double y=1.0) 
  return (int)(x.shape(0)+y);
;

BOOST_PYTHON_MODULE(stupid)

  Py_Initialize();
  np::initialize();
  bp::def("f", f, ( bp::arg("x"), bp::arg("y")=1.0 ) );

::::::::::::::
silly.cpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, np::ndarray * y=nullptr) 
  return (int)(y ? x.shape(0)+y->shape(0) : x.shape(0));
;

BOOST_PYTHON_MODULE(silly)

  Py_Initialize();
  np::initialize();
  bp::def("f", f, ( bp::arg("x"), bp::arg("y")=nullptr ) );


>> make
g++ -I /usr/include/python2.7 -o stupid.so -fPIC -shared stupid.cpp -lboost_python -lboost_numpy -lpython2.7
g++ -I /usr/include/python2.7 -o silly.so  -fPIC -shared silly.cpp  -lboost_python -lboost_numpy -lpython2.7

 >> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22) 
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy; import stupid; stupid.f(numpy.array([1, 2, 3]))
4
>>> import numpy; import silly; silly.f(numpy.array([1, 2, 3]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No to_python (by-value) converter found for C++ type: decltype(nullptr)

解决方法

>> more silly.cpp 
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, bp::object y) 
  np::ndarray yy = np::array(bp::list());
  if (!y.is_none()) yy = bp::extract<np::ndarray>(y);
  return (int)(x.shape(0)+yy.shape(0));
;

BOOST_PYTHON_MODULE(silly)

  Py_Initialize();
  np::initialize();
  bp::def("f", f, ( bp::arg("x"), bp::arg("y") ) );


>> make
g++ -I /usr/include/python2.7 -o silly.so  -fPIC -shared silly.cpp  -lboost_python -lboost_numpy -lpython2.7

>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22) 
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy; import silly; silly.f(numpy.array([1, 2, 3]), numpy.array([1, 2]))
5
>>> import numpy; import silly; silly.f(numpy.array([1, 2, 3]), None)
3

【问题讨论】:

【参考方案1】:

为了能够使用numpy,首先初始化Python运行时和numpy模块:

Py_Initialize();
np::initialize();

未能调用这些会导致分段错误。

================================================ =========================

对于silly.cpp,不需要解决方法。这是实现:

#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::python::numpy;

int f(np::ndarray x, np::ndarray y = np::array(bp::list()) ) 
  return (int)(x.shape(0)+y.shape(0));
;

BOOST_PYTHON_MODULE(silly)

  Py_Initialize();
  np::initialize();
  bp::def("f", f, ( bp::arg("x"), bp::arg("y") = np::array(bp::list()) ) );

以及测试结果:

>>> import numpy, silly; silly.f(numpy.array([1, 2, 3]), numpy.array([1, 2]))
5
>>> import numpy, silly; silly.f(numpy.array([1, 2, 3]))
3

【讨论】:

当然,错过了:尝试在f 中添加这些调用但没有成功... 好的,让它与调用 in BOOST_PYTHON_MODULE 一起工作。仍然使用默认参数 KO(silly 示例) @FGH 我已经删除了 silly.cpp 中的解决方法 - 请参阅我更新的答案。

以上是关于将 boost::python::numpy::ndarray 作为 boost::python 函数的(默认与否)参数传递?的主要内容,如果未能解决你的问题,请参考以下文章

如何将Ios文件上传到

Javascript 将正则表达式 \\n 替换为 \n,将 \\t 替换为 \t,将 \\r 替换为 \r 等等

如何将视频文件转换格式

sh 一个将生成CA的脚本,将CA导入到钥匙串中,然后它将创建一个证书并与CA签名,然后将其导入到

python怎么将0写入文件?

如何将CMD窗口背景改成透明?