संक्षेप में, बूस्ट। पायथन चाल-अर्थशास्त्र का समर्थन नहीं करता है, और इसलिए std::unique_ptr
का समर्थन नहीं करता है। Boost.Python's news/change log का कोई संकेत नहीं है कि इसे C++ 11 move-semantics के लिए अपडेट किया गया है। इसके अतिरिक्त, unique_ptr
समर्थन के लिए एक वर्ष से अधिक समय तक छुआ नहीं गया है।
फिर भी, बूस्ट। पायथन std::auto_ptr
के माध्यम से पाइथन से किसी ऑब्जेक्ट के अनन्य स्वामित्व को स्थानांतरित करने का समर्थन करता है।
- जब अजगर को सी ++ स्थानान्तरण स्वामित्व, सी ++ समारोह चाहिए::
unique_ptr
अनिवार्य रूप से
auto_ptr
के सुरक्षित संस्करण है, यह काफी सीधे आगे एक API
auto_ptr
का उपयोग करता है करने के लिए
unique_ptr
का उपयोग कर एक API अनुकूल करने के लिए किया जाना चाहिए
boost::python::return_value_policy
के कॉलपॉली के साथ boost::python::manage_new_object
परिणाम कनवर्टर के साथ खुलासा किया जाए।
release()
के माध्यम से unique_ptr
रिहाई नियंत्रण है और एक कच्चे सूचक
- जब सी ++ के लिए अजगर स्थानान्तरण स्वामित्व, सी ++ समारोह चाहिए वापसी:
- उदाहरण
auto_ptr
के माध्यम से स्वीकार करते हैं। FAQ का उल्लेख है कि manage_new_object
नीति के साथ C++ से लौटाए गए पॉइंटर्स std::auto_ptr
के माध्यम से प्रबंधित किए जाएंगे। /// @brief Mockup Spam class.
struct Spam;
/// @brief Mockup factory for Spam.
struct SpamFactory
{
/// @brief Create Spam instances.
std::unique_ptr<Spam> make(const std::string&);
/// @brief Delete Spam instances.
void consume(std::unique_ptr<Spam>);
};
SpamFactory::make()
और SpamFactory::consume()
के माध्यम से लिपटे रहने की जरूरत है:
release()
एक API/पुस्तकालय बदला नहीं जा सकता है कि यह देखते हुए के माध्यम से एक unique_ptr
को auto_ptr
रिहाई नियंत्रण है सहायक कार्यों।
कार्य अजगर को C++ से स्वामित्व स्थानांतरित सामान्य रूप से एक समारोह है कि अजगर समारोह वस्तुओं बना दिया जाएगा, लिपटे जा सकता है:
/// @brief Adapter a member function that returns a unique_ptr to
/// a python function object that returns a raw pointer but
/// explicitly passes ownership to Python.
template <typename T,
typename C,
typename ...Args>
boost::python::object adapt_unique(std::unique_ptr<T> (C::*fn)(Args...))
{
return boost::python::make_function(
[fn](C& self, Args... args) { return (self.*fn)(args...).release(); },
boost::python::return_value_policy<boost::python::manage_new_object>(),
boost::mpl::vector<T*, C&, Args...>()
);
}
मूल कार्य करने के लिए लैम्ब्डा प्रतिनिधियों, और अजगर को उदाहरण के releases()
स्वामित्व, और कॉल पॉलिसी इंगित करती है कि पाइथन लैम्ब्डा से लौटाए गए मूल्य का स्वामित्व लेगा। mpl::vector
Boost.Python को कॉल हस्ताक्षर का वर्णन करता है, जो इसे भाषाओं के बीच फ़ंक्शन प्रेषण को व्यवस्थित करने की अनुमति देता है।
adapt_unique
का परिणाम SpamFactory.make()
के रूप में सामने आ रहा है:
boost::python::class_<SpamFactory>(...)
.def("make", adapt_unique(&SpamFactory::make))
// ...
;
सामान्य रूप से अनुकूल SpamFactory::consume()
एक और अधिक कठिन है, लेकिन यह बहुत आसान एक सरल सहायक समारोह लिखने के लिए है:
/// @brief Wrapper function for SpamFactory::consume_spam(). This
/// is required because Boost.Python will pass a handle to the
/// Spam instance as an auto_ptr that needs to be converted to
/// convert to a unique_ptr.
void SpamFactory_consume(
SpamFactory& self,
std::auto_ptr<Spam> ptr) // Note auto_ptr provided by Boost.Python.
{
return self.consume(std::unique_ptr<Spam>{ptr.release()});
}
सहायक समारोह मूल समारोह में प्रतिनिधियों, और auto_ptr
को बूस्ट.पथन द्वारा प्रदान किए गए unique_ptr
को एपीआई द्वारा आवश्यक रूपांतरित करता है।SpamFactory_consume
सहायक समारोह SpamFactory.consume()
के रूप में सामने आ रहा है:
#include <iostream>
#include <memory>
#include <boost/python.hpp>
/// @brief Mockup Spam class.
struct Spam
{
Spam(std::size_t x) : x(x) { std::cout << "Spam()" << std::endl; }
~Spam() { std::cout << "~Spam()" << std::endl; }
Spam(const Spam&) = delete;
Spam& operator=(const Spam&) = delete;
std::size_t x;
};
/// @brief Mockup factor for Spam.
struct SpamFactory
{
/// @brief Create Spam instances.
std::unique_ptr<Spam> make(const std::string& str)
{
return std::unique_ptr<Spam>{new Spam{str.size()}};
}
/// @brief Delete Spam instances.
void consume(std::unique_ptr<Spam>) {}
};
/// @brief Adapter a non-member function that returns a unique_ptr to
/// a python function object that returns a raw pointer but
/// explicitly passes ownership to Python.
template <typename T,
typename ...Args>
boost::python::object adapt_unique(std::unique_ptr<T> (*fn)(Args...))
{
return boost::python::make_function(
[fn](Args... args) { return fn(args...).release(); },
boost::python::return_value_policy<boost::python::manage_new_object>(),
boost::mpl::vector<T*, Args...>()
);
}
/// @brief Adapter a member function that returns a unique_ptr to
/// a python function object that returns a raw pointer but
/// explicitly passes ownership to Python.
template <typename T,
typename C,
typename ...Args>
boost::python::object adapt_unique(std::unique_ptr<T> (C::*fn)(Args...))
{
return boost::python::make_function(
[fn](C& self, Args... args) { return (self.*fn)(args...).release(); },
boost::python::return_value_policy<boost::python::manage_new_object>(),
boost::mpl::vector<T*, C&, Args...>()
);
}
/// @brief Wrapper function for SpamFactory::consume(). This
/// is required because Boost.Python will pass a handle to the
/// Spam instance as an auto_ptr that needs to be converted to
/// convert to a unique_ptr.
void SpamFactory_consume(
SpamFactory& self,
std::auto_ptr<Spam> ptr) // Note auto_ptr provided by Boost.Python.
{
return self.consume(std::unique_ptr<Spam>{ptr.release()});
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<Spam, boost::noncopyable>(
"Spam", python::init<std::size_t>())
.def_readwrite("x", &Spam::x)
;
python::class_<SpamFactory>("SpamFactory", python::init<>())
.def("make", adapt_unique(&SpamFactory::make))
.def("consume", &SpamFactory_consume)
;
}
इंटरएक्टिव पायथन:
>>> import example
>>> factory = example.SpamFactory()
>>> spam = factory.make("a" * 21)
Spam()
>>> spam.x
21
>>> spam.x *= 2
>>> spam.x
42
>>> factory.consume(spam)
~Spam()
>>> spam.x = 100
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
None.None(Spam, int)
did not match C++ signature:
None(Spam {lvalue}, unsigned int)
विस्तृत उत्तर के लिए बहुत बहुत धन्यवाद! मैं इसे जल्द से जल्द कोशिश करूँगा, लेकिन कोड अच्छा दिखता है! – schlimpf
और std :: unique_ptr के बारे में क्या है जिसे add_property के रूप में परिभाषित किया गया है। क्या मुझे इसे क्लास परिभाषा पर लपेटना है, जहां मैं वास्तव में संपत्ति जोड़ रहा हूं या_python_converter को परिभाषित करना बेहतर अभ्यास होगा? –