以其他类的数组作为参数公开构造函数
Exposing constructor with an array of other class as argument
我有两个不同的类,我想使用boost python公开它们,但第二个类的构造函数将第一个类的数组作为参数,我不知道如何做到这一点。
这是类的定义:
class INT96{
public:
uint64_t value[3];
INT96(){};
INT96(uint64_t x0, uint64_t x1, uint64_t x2);
...
};
template <unsigned k>
class Xi_CW{
protected:
INT96 A[k];
public:
Xi_CW(INT96 (&A)[k]);
...
};
我尝试使用boost-python:来揭露它们
using namespace boost::python;
typedef Xi_CW<4> Xi_CW4;
BOOST_PYTHON_MODULE(xis)
{
class_<INT96>("INT96", init<double,double,double>())
[...]
;
class_<Xi_CW4>("Xi_CW4", init<INT96[4]>())
[...]
;
}
这会导致"未知的转换错误"。我试过其他几种可能性,但到目前为止运气不好。。。
知道我该怎么做吗?感谢
我相信您可以使用boost::python::list为您的构造函数接收一个int96数组,然后根据需要将其转换为常规c++数组。
下面是我发现的一个将python可迭代项转换为c++向量的示例:https://stackoverflow.com/a/19092051/996197
一个解决方案是取消Boost.Python默认初始化器,并注册一个custon初始化器,该初始化器可以从包含INT96
对象的可迭代Python对象构造Xi_CW<4>
对象。
- 通过
boost::python::class_
公开类时,可以通过提供boost::python::no_init
作为init_spec
来抑制默认初始值设定项 - 由
boost::python::make_constructor()
封装的辅助函数可以作为类上的__init__
方法公开
以下是一个基于原始问题中给出的类型的完整示例:
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/python.hpp>
/// @brief Mockup spam class.
struct spam
{
int value[3];
spam() {};
spam(int x, int y, int z)
{
value[0] = x;
value[1] = y;
value[2] = z;
}
};
/// @brief Mockup egg class.
template <std::size_t N>
class egg
{
public:
explicit egg(spam (&spams)[N]) : spams_(spams) {}
/// @brief Return string reprenstation of the egg class.
std::string to_string()
{
std::stringstream stream;
stream << "[";
BOOST_FOREACH(spam& s, spams_)
{
stream << "[" << s.value[0] << ", "
<< s.value[1] << ", "
<< s.value[2]
<< "]";
}
stream << "]";
return stream.str();
}
private:
spam spams_[N];
};
/// @brief Auxiliary function that will attempt to create an egg<N> type
/// from an iterable Python object that contains spam objects.
template <std::size_t N>
egg<N>* make_egg(boost::python::object object)
{
spam spams[N];
// Iterate over the python object, extracting and copying spam objects.
// Boost.Python will handle throwing exceptions for the appropriate cases:
// - object does not support indexing (__getitem__)
// - object[N-1] is out of range
// - object[i] does not contain or cannot be converted to a spam&
for (long i = 0; i < N; ++i)
spams[i] = boost::python::extract<spam&>(object[i]);
// Construct egg from the local spam array. Ownership of the object is
// passed to Boost.Python
return new egg<N>(spams);
}
/// @brief Expose an egg<N> type to Python.
///
/// @param name The name that will be exposed to Python.
template <std::size_t N>
boost::python::class_<egg<N> > expose_egg(const char* name)
{
namespace python = boost::python;
// Explicitly suppress the Boost.Python default constructor.
typedef egg<N> egg_type;
python::class_<egg_type> egg_class(name, python::no_init);
// Register a custom factory function as the constructor method.
egg_class
.def("__init__", python::make_constructor(&make_egg<N>))
.def("__str__", &egg_type::to_string)
;
return egg_class;
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose spam.
python::class_<spam>("Spam", python::init<int, int, int>());
// Expose different egg types.
expose_egg<2>("Egg2");
expose_egg<4>("Egg4");
}
交互式使用:
>>> import example
>>> spams = [
... example.Spam(0, 1, 2),
... example.Spam(1, 2, 3),
... example.Spam(2, 3, 4),
... example.Spam(3, 4, 5)
... ]
>>> print example.Egg2(spams)
[[0, 1, 2][1, 2, 3]]
>>> print example.Egg4(tuple(spams)) # different type
[[0, 1, 2][1, 2, 3][2, 3, 4][3, 4, 5]]
>>> print example.Egg4(spams[:1]) # expect IndexError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> print example.Egg4(42) # expect TypeError (42[0] is invalid)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object has no attribute '__getitem__'
>>> print example.Egg4([42]) # expect TypeError (conversion)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: No registered converter was able to extract a C++ reference to
type spam from this Python object of type int
相关文章:
- C++:使用运算符 = 调用多参数构造函数
- 通过零参数构造函数创建的 glm::mat4 应该包含哪些值?
- 好奇的混合与可变参数构造函数
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 为什么我们需要创建一个单参数构造函数来使用临时的无名称对象
- 在可变参数构造函数中初始化常量数组
- C++ 显式多参数构造函数歧义
- 零一参数构造函数
- 可变参数构造函数中的 SFINAE
- 当没有显式关键字与单参数构造函数一起使用时,编译器可以发出警告
- 可变参数类模板和可变参数构造函数
- 确保模板参数类型与其可变参数构造函数的类型匹配
- C++默认参数构造函数与内联初始化优先级
- 如何在 c++ 中将包含复制构造函数的类的参数构造函数称为私有?
- 自动存储中没有无参数构造函数的类对象和异常
- 警告:用两个参数构造函数返回对象时,表达结果未使用
- 如何在C++中调用无参数构造函数
- 在 c++ 中具有多个参数构造函数的模板类存在问题
- 可变参数构造函数优先于用户提供的移动构造函数,除非默认
- 如何从可变参数构造函数参数构造任何对象?