aboutsummaryrefslogtreecommitdiffstats
path: root/host/python/pyuhd.cpp
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-02-04 16:00:16 +0100
committerMartin Braun <martin.braun@ettus.com>2019-02-22 16:56:52 -0800
commit692ddc71b17196487dcad982836e074cab9a0f25 (patch)
treecf76abf577dde6128e03561c52d9c31dca302026 /host/python/pyuhd.cpp
parent51bbf548c9b442d0b53b6c8de5f89403de274424 (diff)
downloaduhd-692ddc71b17196487dcad982836e074cab9a0f25.tar.gz
uhd-692ddc71b17196487dcad982836e074cab9a0f25.tar.bz2
uhd-692ddc71b17196487dcad982836e074cab9a0f25.zip
python: Replace Boost.Python with PyBind11
This does not change the Python API itself, but it is still a significant change. Most importantly, it removes the dependency on Boost.Python.
Diffstat (limited to 'host/python/pyuhd.cpp')
-rw-r--r--host/python/pyuhd.cpp179
1 files changed, 24 insertions, 155 deletions
diff --git a/host/python/pyuhd.cpp b/host/python/pyuhd.cpp
index e0f35d929..16badbe8c 100644
--- a/host/python/pyuhd.cpp
+++ b/host/python/pyuhd.cpp
@@ -1,29 +1,21 @@
//
// Copyright 2017-2018 Ettus Research, a National Instruments Company
+// Copyright 2019 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
-#include <boost/shared_ptr.hpp>
-#include <boost/python.hpp>
-#include <boost/python/stl_iterator.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-
-/*
-This solution was adapted from an Issue posted to the Boost.Python Github.
-https://github.com/boostorg/python/pull/159/files
-*/
-#if (BOOST_VERSION >= 106400) && (BOOST_VERSION < 106600)
-#warning overriding broken boost python implementation of BOOST_PYTHON_MODULE_INIT
-# define BOOST_PYTHON_MODULE_INIT(name) \
- void BOOST_PP_CAT(init_module_,name)(); \
-extern "C" BOOST_SYMBOL_EXPORT _BOOST_PYTHON_MODULE_INIT(name)
-#endif
+#include <pybind11/pybind11.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>
-namespace bp = boost::python;
+namespace py = pybind11;
+
+// Allow boost::shared_ptr<T> to be a holder class of an object (PyBind11
+// supports std::shared_ptr and std::unique_ptr out of the box)
+#include <boost/shared_ptr.hpp>
+PYBIND11_DECLARE_HOLDER_TYPE(T, boost::shared_ptr<T>);
#include "stream_python.hpp"
@@ -40,81 +32,6 @@ namespace bp = boost::python;
#include "usrp/subdev_spec_python.hpp"
#include "usrp/multi_usrp_python.hpp"
-// Converter for std::vector / std::list arguments from python iterables
-struct iterable_converter
-{
- template <typename Container>
- iterable_converter& from_python()
- {
- bp::converter::registry::push_back(
- &iterable_converter::convertible,
- &iterable_converter::construct<Container>,
- bp::type_id<Container>()
- );
- return *this;
- }
-
- static void* convertible(PyObject* object)
- {
- return PyObject_GetIter(object) ? object : NULL;
- }
-
- template <typename Container>
- static void construct(
- PyObject* object,
- bp::converter::rvalue_from_python_stage1_data* data)
- {
- // Object is a borrowed reference, so create a handle indicting it is
- // borrowed for proper reference counting.
- bp::handle<> handle(bp::borrowed(object));
-
- // Obtain a handle to the memory block that the converter has
- // allocated for the C++ type.
- typedef bp::converter::rvalue_from_python_storage<Container> storage_type;
-
- void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
- typedef bp::stl_input_iterator<typename Container::value_type> iterator;
-
- // Allocate the C++ type into the converter's memory block, and assign
- // its handle to the converter's convertible variable. The C++
- // container is populated by passing the begin and end iterators of
- // the python object to the container's constructor.
- new (storage) Container(
- iterator(bp::object(handle)), // begin
- iterator() // end
- );
-
- data->convertible = storage;
- }
-};
-
-template<typename Dtype1, typename Dtype2>
-struct uhd_to_python_dict
-{
- static PyObject* convert(uhd::dict<Dtype1, Dtype2> const& input_dict)
- {
- bp::dict py_dict;
- for (const auto& key: input_dict.keys()){
- py_dict[key] = input_dict[key];
- }
- return bp::incref(py_dict.ptr());
- }
-
-};
-
-template<typename Container>
-struct iterable_to_python_list
-{
- static PyObject* convert(Container const& input)
- {
- bp::list py_list;
- for (const auto& element: input){
- py_list.append(element);
- }
- return bp::incref(py_list.ptr());
- }
-};
-
// We need this hack because import_array() returns NULL
// for newer Python versions.
// This function is also necessary because it ensures access to the C API
@@ -132,80 +49,32 @@ void init_numpy()
}
#endif
-BOOST_PYTHON_MODULE(libpyuhd)
+PYBIND11_MODULE(libpyuhd, m)
{
// Initialize the numpy C API
// (otherwise we will see segmentation faults)
init_numpy();
- bp::object package = bp::scope();
- package.attr("__path__") = "libpyuhd";
-
- // Declare converters
- iterable_converter()
- .from_python<std::vector<double> >()
- .from_python<std::vector<int> >()
- .from_python<std::vector<size_t> >()
- ;
-
- bp::to_python_converter<
- uhd::dict<std::string, std::string>,
- uhd_to_python_dict<std::string, std::string>, false >();
- bp::to_python_converter<
- std::vector<std::string>,
- iterable_to_python_list<std::vector<std::string> >, false >();
-
// Register types submodule
- {
- bp::object types_module(
- bp::handle<>(bp::borrowed(PyImport_AddModule("libpyuhd.types")))
- );
- bp::scope().attr("types") = types_module;
- bp::scope io_scope = types_module;
-
- bp::implicitly_convertible<std::string, uhd::device_addr_t>();
-
- export_types();
- export_time_spec();
- export_spi_config();
- export_metadata();
- export_sensors();
- export_tune();
+ auto types_module = m.def_submodule("types", "UHD Types");
- // Declare some more converters
- iterable_converter()
- .from_python<std::vector<uhd::device_addr_t>>()
- ;
-
- bp::to_python_converter<
- std::vector<uhd::device_addr_t>,
- iterable_to_python_list<std::vector<uhd::device_addr_t>>, false >();
- }
+ export_types(types_module);
+ export_time_spec(types_module);
+ export_spi_config(types_module);
+ export_metadata(types_module);
+ export_sensors(types_module);
+ export_tune(types_module);
// Register usrp submodule
- {
- bp::object usrp_module(
- bp::handle<>(bp::borrowed(PyImport_AddModule("libpyuhd.usrp")))
- );
- bp::scope().attr("usrp") = usrp_module;
- bp::scope io_scope = usrp_module;
-
- export_multi_usrp();
- export_subdev_spec();
- export_dboard_iface();
- export_fe_connection();
- export_stream();
- }
+ auto usrp_module = m.def_submodule("usrp", "USRP Objects");
+ export_multi_usrp(usrp_module);
+ export_subdev_spec(usrp_module);
+ export_dboard_iface(usrp_module);
+ export_fe_connection(usrp_module);
+ export_stream(usrp_module);
// Register filters submodule
- {
- bp::object filters_module(
- bp::handle<>(bp::borrowed(PyImport_AddModule("libpyuhd.filters")))
- );
- bp::scope().attr("filters") = filters_module;
- bp::scope io_scope = filters_module;
-
- export_filters();
- }
+ auto filters_module = m.def_submodule("filters", "Filter Submodule");
+ export_filters(filters_module);
}