From dcba6c6fa9d970d88f41036d361e9c39a623b95e Mon Sep 17 00:00:00 2001 From: Sebastiaan van der Tol <tol@astron.nl> Date: Mon, 2 May 2022 12:13:32 +0200 Subject: [PATCH] Add pybind11 module using std::unique_ptr argument --- .gitmodules | 3 ++ CMakeLists.txt | 12 +++++++ external/pybind11 | 1 + mymodule.cc | 82 +++++++++++++++++++++++++++++++++++++++++++++++ testmymodule.py | 18 +++++++++++ 5 files changed, 116 insertions(+) create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 160000 external/pybind11 create mode 100644 mymodule.cc create mode 100755 testmymodule.py diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7676f39 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/pybind11"] + path = external/pybind11 + url = https://github.com/pybind/pybind11.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ae071c5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.8) + +project(pybind11-std-unique-ptr) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED YES) + +add_subdirectory("${CMAKE_SOURCE_DIR}/external/pybind11") + +pybind11_add_module(mymodule mymodule.cc) + +#include_directories(${pybind11_INCLUDE_DIRS}) \ No newline at end of file diff --git a/external/pybind11 b/external/pybind11 new file mode 160000 index 0000000..75007dd --- /dev/null +++ b/external/pybind11 @@ -0,0 +1 @@ +Subproject commit 75007dda72ad4508064c1f080394eae50d3a61ee diff --git a/mymodule.cc b/mymodule.cc new file mode 100644 index 0000000..8a1e185 --- /dev/null +++ b/mymodule.cc @@ -0,0 +1,82 @@ +#include <iostream> +#include <string> + +#include <pybind11/pybind11.h> + +namespace py = pybind11; + +// template<typename T> std::unique_ptr<T> py_unique_ptr(T &object) { +// py::object py_object(pybind11::cast(&object)); +// return std::unique_ptr<T>(&object, [](T* p){}); +// } + +class Pet { + public: + + Pet(const std::string &name) : + name_(name) + { + std::cout << "A pet named " << name_ << " came to life." << std::endl; + } + + // Option 1 - no move constructor - moving will make a copy + // + // Pet(Pet &&other)=delete; + + // Option 2 - default move constructor - members will be moved into new object + // Pet(Pet &&other)=default; + + // Option 3 - Custom move constructor + Pet(Pet &&other) : + name_((std::move(other.name_))) + { + std::cout << "Moving " << name_ << " to new pet." << std::endl; + } + + virtual ~Pet() + { + std::cout << "A pet named '" << name_ << "' died." << std::endl; + } + + std::string GetName() {return name_;} + + private: + std::string name_; +}; + +class PetHolder { + public: + PetHolder(std::unique_ptr<Pet> pet) : + pet_(std::move(pet)) + {} + + std::string GetPetName() const { + return pet_->GetName(); + } + + void SetPet(std::unique_ptr<Pet> pet) { + pet_ = std::move(pet); + } + private: + std::unique_ptr<Pet> pet_; + +}; + +class PyPetHolder : public PetHolder { + public: + PyPetHolder(Pet &pet) : PetHolder(std::make_unique<Pet>(std::move(pet))) + {} +}; + +PYBIND11_MODULE(mymodule, m) { + m.doc() = R"pbdoc( + module to demonstrate handling of std::unique_ptr arguments in pybind11. + )pbdoc"; + + py::class_<Pet>(m, "Pet") + .def(py::init<const std::string &>()); + + py::class_<PyPetHolder>(m, "PetHolder") + .def(py::init<Pet&>()); + +} diff --git a/testmymodule.py b/testmymodule.py new file mode 100755 index 0000000..918aa11 --- /dev/null +++ b/testmymodule.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Output: + +# A pet named Tweety came to life. +# Moving Tweety to new pet. +# A pet named '' died. +# A pet named 'Tweety' died. + +import mymodule + +t = mymodule.Pet("Tweety") + +h = mymodule.PetHolder(t) + +del t +del h + -- GitLab