This and that learned from boost.python

This and that learned from boost.python

I would like to write what I learned by using boost.python.

Add module global variables

Thing you want to do

>>> import hoge
>>> hoge.GLOBAL_VALUE
1

Use boost :: python :: scope.

BOOST_PYTHON_MODULE(hoge)
{
    boost::python::scope().attr("GLOBAL_VALUE") = 1;
}

Define __str__, __repr__

Thing you want to do

>>> import hoge
>>> h = hoge.hoge()
>>> print h
hoge
>>> h
hoge

I think there are many ways to do this, but it's a way to convert from std :: ostream to python's __str__, __repr__.

class hoge
{
};

std::ostream& operator<<(std::ostream& out, const hoge& )
{
    out << "hoge";
    return out;
}

BOOST_PYTHON_MODULE(hoge)
{
    using namespace boost::python;
    class_<hoge>("hoge")
	.def(self_ns::str(self))
	.def(self_ns::repr(self));
}

Access members of the struct

Thing you want to do

>>> import hoge
>>> f = hoge.foo()
>>> f.a
0
>>> f.a = 5
>>> f.a
5

Use def_readwrite.

struct foo
{
    int a;
    foo(): a(0){};
};

BOOST_PYTHON_MODULE(hoge)
{
    using namespace boost::python;
    class_<foo>("foo")
	.def_readwrite("a", &foo::a);
}

Use the default arguments of the function

Thing you want to do

>>> import hoge
>>> hoge.add(1)
1
>>> hoge.add(1, 2)
3
>>> hoge.add(1, 2, 3)
6

Use BOOST_PYTHON_FUNCTION_OVERLOADS or BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS. BOOST_PYTHON_FUNCTION_OVERLOADS (add_overloads, add, 1, 3) sets the number of minimum arguments to ʻadd` to 1 and the number of maximum arguments to 3.

int add(int a, int b = 0, int c = 0)
{
    return a + b + c;
}

BOOST_PYTHON_FUNCTION_OVERLOADS(add_overloads, add, 1, 3)

BOOST_PYTHON_MODULE(hoge)
{
    using namespace boost::python;
    def("add", add, add_overloads());
}

Do the above example with variable arguments

Thing you want to do

>>> import hoge
>>> hoge.add(1, 2, 3, a = 4, c = 5)
>>> 15
using namespace boost::python;

int add(tuple args, dict kw)
{
    int sum = 0;
    for (int i = 0; i < len(args); ++i)
    {
	sum += extract<int>(args[i]);
    }
    list vals = kw.values();
    for (int i = 0; i < len(vals); ++i)
    {
	sum += extract<int>(vals[i]);
    }
    return sum;
}

BOOST_PYTHON_MODULE(hoge)
{
    def("add", raw_function(add));
}

Convert boost :: posix_time :: ptime to datetime

Thing you want to do

>>> import hoge
>>> f = hoge.foo()
>>> f.now()
datetime.datetime(2015, 12, 30, 15, 29, 12)
>>> f.now()
datetime.datetime(2015, 12, 30, 15, 29, 14)
static long get_usecs(boost::posix_time::time_duration const& d)
{
    static long resolution
	= boost::posix_time::time_duration::ticks_per_second();
    long fracsecs = d.fractional_seconds();
    if (resolution > 1000000)
	return fracsecs / (resolution / 1000000);
    else
	return fracsecs * (1000000 / resolution);
}


struct ptime_to_python_datetime
{
    static PyObject* convert(boost::posix_time::ptime const& pt)
    {
        boost::gregorian::date date = pt.date();
        boost::posix_time::time_duration td = pt.time_of_day();
        return PyDateTime_FromDateAndTime((int)date.year(),
					  (int)date.month(),
					  (int)date.day(),
					  td.hours(),
					  td.minutes(),
					  td.seconds(),
					  get_usecs(td));
    }
};

class foo
{
public:
    boost::posix_time::ptime now()
    {
	return boost::posix_time::second_clock::local_time();
    }
};

BOOST_PYTHON_MODULE(hoge)
{
    using namespace boost::python;
    PyDateTime_IMPORT;

    to_python_converter<const boost::posix_time::ptime, ptime_to_python_datetime>();

    class_<foo>("foo")
	.def("now", &foo::now);
}

I want the struct to have a datetime

Thing you want to do

>>> import hoge
>>> import datetime
>>> h = hoge.hoge()
>>> h.date = datetime.datetime.now()
>>> h.date
datetime.datetime(2015, 12, 30, 15, 40, 6, 406588)

I can't use the def_readwrite I used earlier, but use ʻadd_property`.

//Ptime used in the above example_to_python_Write the datetime in the same way.

struct ptime_from_python_datetime
{
     ptime_from_python_datetime()
     {
         boost::python::converter::registry::push_back(&convertible,
						       &construct,
						       boost::python::type_id<boost::posix_time::ptime>());
     }

     static void* convertible(PyObject * obj_ptr)
     {
	 if (!PyDateTime_Check(obj_ptr))
	     return 0;
	 return obj_ptr;
     }

     static void construct(PyObject* obj_ptr,
			   boost::python::converter::rvalue_from_python_stage1_data * data)
     {
	 PyDateTime_DateTime const* pydate
	     = reinterpret_cast<PyDateTime_DateTime*>(obj_ptr);

	 // Create date object
	 boost::gregorian::date _date(PyDateTime_GET_YEAR(pydate),
				      PyDateTime_GET_MONTH(pydate),
				      PyDateTime_GET_DAY(pydate));

	 // Create time duration object
	 boost::posix_time::time_duration
	     _duration(PyDateTime_DATE_GET_HOUR(pydate),
		       PyDateTime_DATE_GET_MINUTE(pydate),
		       PyDateTime_DATE_GET_SECOND(pydate),
		       0);
	 // Set the usecs value
	 _duration += boost::posix_time::microseconds(PyDateTime_DATE_GET_MICROSECOND(pydate));

	 // Create posix time object
	 void* storage = ((boost::python::converter::rvalue_from_python_storage<boost::posix_time::ptime>*)
			  data)->storage.bytes;
	 new(storage) boost::posix_time::ptime(_date, _duration);
	 data->convertible = storage;
     }
};

struct hoge
{
    boost::posix_time::ptime date;
};

BOOST_PYTHON_MODULE(hoge)
{
    using namespace boost::python;
    PyDateTime_IMPORT;

    ptime_from_python_datetime();
    to_python_converter<const boost::posix_time::ptime, ptime_to_python_datetime>();

    class_<hoge>("hoge")
	.add_property("date",
		      make_getter(&hoge::date, return_value_policy<return_by_value>()),
		      make_setter(&hoge::date, return_value_policy<copy_non_const_reference>()));

}

Handle std :: vector

Thing you want to do

>>> import hoge
>>> v = hoge.DoubleVector()
>>> v.append(1.0)
>>> v.append(2.0)
>>> v[0]
1.0
>>> v[1]
2.0

Use vector_indexing_suite.

BOOST_PYTHON_MODULE(hoge)
{
    using namespace boost::python;
    class_<std::vector<double> >("DoubleVector")
        .def(vector_indexing_suite<std::vector<double> >());
}

Use std :: map

Thing you want to do

>>> import hoge
>>> m = hoge.StringDoubleMap()
>>> m["a"] = 1
>>> m["b"] = 2
>>> m["a"]
1.0
>>> m["b"]
2.0

Use map_indexing_suite.

BOOST_PYTHON_MODULE(hoge)
{
    using namespace boost::python;
    class_<std::map<std::string, double> >("StringDoubleMap")
        .def(map_indexing_suite<std::map<std::string, double> >());
}

Recommended Posts

This and that learned from boost.python
matplotlib this and that
This and that about pd.DataFrame
This and that using reflect
Zabbix API this and that
This and that of python properties
This and that using NLTK (memo)
This and that of the inclusion notation.
This and that useful when used with nohup
This time I learned Python I and II at Progate.
Iptables learned from documentation
This and that around Mysql in Apache environment (Note)
This time I learned python III and IV with Prorate
This and that for using Step Functions with CDK + Python
Deep Python learned from DEAP
Programming Learned from Books May 9
Programming learned from books May 11