python - Boost.Python:匹配 C++ 模板类型的嵌套命名空间
问题描述
尝试使用 Boost.Python 将 python numpy 数组传递给 C++,在 C++ 中处理它们,并将处理结果返回给 python :由于数组的类型是在 C++ 端模板化的,它应该匹配 python 端的嵌套命名空间。
尽管进行了许多测试/谷歌搜索,但仍未找到解决方案。
错误:“Boost.Python.ArgumentError python 参数类型与 C++ 签名不匹配”:任何线索?...
>> more dummy.hpp dummy.cpp dummy.py
::::::::::::::
dummy.hpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
namespace bp = boost::python;
namespace np = boost::python::numpy;
template<typename FD>
class dummy {
public:
dummy() {
Py_Initialize();
np::initialize();
mean = 0.;
};
int doStuffs(np::ndarray & A) {
int szA = A.shape(0);
FD * ptrA = reinterpret_cast<FD*>(A.get_data());
for (int i = 0; i < szA; ++i) {
std::cout << "dummy::doStuffs - " << i << " : " << ptrA[i] << std::endl;
mean += ptrA[i];
}
mean /= szA;
std::cout << "dummy::doStuffs, mean " << mean << std::endl;
return 0;
};
FD mean;
};
template<typename FD>
void exportDummy(std::string const & nested) {
std::string module = "dummy." + nested;
bp::object pyModule(bp::handle<>(bp::borrowed(PyImport_AddModule(module.c_str()))));
bp::scope().attr(nested.c_str()) = pyModule;
bp::scope pyScope = pyModule;
bp::class_<dummy<FD>, boost::noncopyable>(nested.c_str())
.def ("doStuffs", &dummy<FD>::doStuffs)
.def_readonly ("mean", &dummy<FD>::mean);
};
::::::::::::::
dummy.cpp
::::::::::::::
#include <boost/python.hpp>
#include <dummy.hpp>
namespace bp = boost::python;
BOOST_PYTHON_MODULE(dummy)
{
// Specify that this module is actually a package.
bp::object package = bp::scope();
package.attr("__path__") = "dummy"; // Setting the __path__ attribute on the module to the name of the module.
// Create modules.
exportDummy<float>("float");
}
::::::::::::::
dummy.py
::::::::::::::
#!/usr/bin/env python
from __future__ import print_function
import numpy as np
from scipy import sparse
n = 4
one = np.array([ 1]*n)
data = np.array([2.*one, -1.*one, -1.*one])
diags = np.array([0, 1, -1])
A = sparse.spdiags(data, diags, n, n)
print("python A ", A.toarray())
import dummy
dummyFloat = dummy.float.float()
dummyFloat.doStuffs(A)
print("python mean", dummyFloat.mean)
我得到:
>> make
g++ -I/usr/include/python2.7 -I. -fPIC -shared -o dummy.so dummy.cpp -lboost_numpy -lboost_python -lpython2.7
>> python dummy.py
python A [[ 2. -1. 0. 0.]
[-1. 2. -1. 0.]
[ 0. -1. 2. -1.]
[ 0. 0. -1. 2.]]
Traceback (most recent call last):
File "dummy.py", line 17, in <module>
dummyFloat.doStuffs(A)
Boost.Python.ArgumentError: Python argument types in
float.doStuffs(float, dia_matrix)
did not match C++ signature:
doStuffs(dummy<float> {lvalue}, boost::python::numpy::ndarray {lvalue})
解决方案
找到解决方案!
>> more dummy.cpp dummy.hpp dummy.py
::::::::::::::
dummy.cpp
::::::::::::::
#include <boost/python.hpp>
#include <complex>
#include <dummy.hpp>
namespace bp = boost::python;
BOOST_PYTHON_MODULE(dummy)
{
bp::object package = bp::scope();
package.attr("__path__") = "dummy";
exportDummy<float>("float");
exportDummy<complex<float>>("complexFloat");
}
::::::::::::::
dummy.hpp
::::::::::::::
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
namespace bp = boost::python;
namespace np = boost::python::numpy;
using namespace std;
template<typename FD>
class dummy {
public:
dummy() {
Py_Initialize();
np::initialize();
mean = 0.;
};
int doStuffs(np::ndarray & A) {
int szA = A.shape(0);
FD * ptrA = reinterpret_cast<FD*>(A.get_data());
for (int i = 0; i < szA; ++i) {
std::cout << "C++ - dummy::doStuffs - " << i << " : " << ptrA[i] << std::endl;
mean += ptrA[i];
}
mean /= szA;
return 0;
};
FD mean;
};
template<typename FD>
void exportDummy(std::string const & nested) {
std::string module = "dummy";
bp::object pyModule(bp::handle<>(bp::borrowed(PyImport_AddModule(module.c_str()))));
bp::scope pyScope = pyModule;
pyScope.attr(nested.c_str()) = bp::class_<dummy<FD>, boost::noncopyable>(nested.c_str())
.def ("doStuffs", &dummy<FD>::doStuffs)
.def_readonly("mean", &dummy<FD>::mean)
;
};
::::::::::::::
dummy.py
::::::::::::::
#!/usr/bin/env python
from __future__ import print_function
import numpy as np
import dummy
A = np.array([1, 2, 3], dtype='float32')
print("python A ", A)
df = dummy.float()
df.doStuffs(A)
print("python mean", df.mean)
A = np.array([1+2j, 3+4j, 5+6j], dtype='complex64')
print("python A ", A)
dcf = dummy.complexFloat()
dcf.doStuffs(A)
print("python mean", dcf.mean)
我得到:
>> make
g++ -I/usr/include/python2.7 -I. -fPIC -shared -o dummy.so dummy.cpp -lboost_numpy -lboost_python -lpython2.7
>> python dummy.py
python A [1. 2. 3.]
C++ - dummy::doStuffs - 0 : 1
C++ - dummy::doStuffs - 1 : 2
C++ - dummy::doStuffs - 2 : 3
python mean 2.0
python A [1.+2.j 3.+4.j 5.+6.j]
C++ - dummy::doStuffs - 0 : (1,2)
C++ - dummy::doStuffs - 1 : (3,4)
C++ - dummy::doStuffs - 2 : (5,6)
python mean (3+4j)
推荐阅读
- javascript - 如何将值(不是通过引用)传递给javascript中的数组
- powershell - 如何给数组编号并输出到屏幕
- python - 带有预设值的可编辑标签的 DocuSign 信封
- spring - 得到错误 org.h2.jdbc.JdbcSQLSyntaxErrorException:找不到序列“HIBERNATE_SEQUENCE”;SQL 语句:
- scala - Spark时间戳列不可序列化错误
- android - 当 editText.isNotBlank() 和 checkBox.isChecked 时,如何启用按钮?
- unity3d - 在同一轴上同时旋转两次
- python - 使用 pandas 连接两个数据框
- c# - 代码卡在 Microsoft.SharePoint.Client.File.OpenBinaryDirect 方法
- apache-kafka - 当我们使用 auto.offset.reset=latest kafka 属性时是否需要 FlinkKafkaConsumer setStartFromLatest() 方法