2014-07-04 3 views
8

का उपयोग कर रहा Boost.Python का उपयोग कर पायथन के लिए निम्न सी ++ समारोह का पर्दाफाश करना चाहते हैं:उजागर सी ++ काम करता है, कि वापसी सूचक Boost.Python

int* test1() { 
    return new int(42); 
} 

// Now exposing the function with Boost.Python 

BOOST_PYTHON_MODULE(libtest1) 
{ 
    using namespace boost::python; 
    def("test1", test1); 
} 

जब मैं की वजह से इस पुस्तकालय त्रुटि तब होती है संकलन करने की कोशिश (यह मेरा अनुमान) बूस्ट। पाइथन नहीं जानता, Int * को PyObject में कैसे परिवर्तित करें।

template<class T> 
struct int_ptr_to_python 
{ 
    static PyObject* convert(int* i_ptr) 
    { 
     return i_ptr; 
    } 
}; 

और यह BOOST_PYTHON_MODULE घोषणा करने के लिए पारित:

मैं क्या रूपांतरण संरचना, कुछ इस तरह परिभाषित करने के लिए किया जाता है किया जाना चाहिए लगता है

BOOST_PYTHON_MODULE(libtest1) 
{ 
    using namespace boost::python; 
    def("test1", test1); 
    to_python_converter<int*, int_ptr_to_python<int*> >(); 
} 

लेकिन यह भी काम नहीं करता है । और मुझे फ़ंक्शंस को कैसे प्रबंधित किया जाना चाहिए, इस बारे में कोई जानकारी नहीं मिल सकती है।

क्या कोई मदद कर सकता है?

उत्तर

11

संक्षेप में, कोई भी बूस्ट.पथन के साथ int* लौटने वाले फ़ंक्शन का सीधे खुलासा नहीं कर सकता है, क्योंकि पाइथन दिए गए पूर्णांक में कोई सार्थक संबंधित प्रकार अपरिवर्तनीय नहीं है।

  • यदि लक्ष्य पायथन पर एक नंबर वापस करना है, तो मूल्य के अनुसार int वापस करें। विरासत एपीआई को अनुकूलित करने के लिए इसे सहायक फ़ंक्शन का उपयोग करने की आवश्यकता हो सकती है।
  • यदि लक्ष्य एक नई अभिव्यक्ति के साथ आवंटित ऑब्जेक्ट में पॉइंटर वापस करना है, तो ऑब्जेक्ट एक वर्ग या संघ होना चाहिए, और फ़ंक्शन को स्वामित्व जिम्मेदारियों को इंगित करने के लिए विशिष्ट नीतियों के साथ अवगत कराया जाना चाहिए।

बल्कि अंतिम समाधान तुरंत वर्तमान की तुलना में, मैं समय संकलक त्रुटियों से निकलने के लिए लेना चाहते हैं। Boost.Python के साथ, कभी-कभी पूर्व-सी ++ 11 स्थैतिक दावे का उपयोग कंपाइलर संदेशों में निर्देश प्रदान करने के लिए किया जाता है। दुर्भाग्यवश, भारी टेम्पलेट्स में उन्हें ढूंढना थोड़ा मुश्किल हो सकता है।

निम्नलिखित कोड:

#include <boost/python.hpp> 

int* make_int() { return new int(42); } 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::def("make_int", &make_int); 
} 

, बजना में निम्नलिखित प्रासंगिक उत्पादन का उत्पादन बोल्ड में बल महत्वपूर्ण विवरण के साथ:

 
.../boost/python/detail/caller.hpp:102:98: error: 
    no member named 'get_pytype' in 'boost::python::detail:: 
    specify_a_return_value_policy_to_wrap_functions_returning<int*>' 
    ...create_result_converter((PyObject*)0, (ResultConverter *)0, 
          (ResultConverter *)0).g... 

Boost.Python में हमें जानकारी देने जाता है कि एक boost::python::return_value_policy जरूरतों होने के लिए int* लौटने वाले कार्यों के लिए निर्दिष्ट। ResultConverterGenerators के विभिन्न मॉडल हैं। अक्सर बार-बार लौटाई गई वस्तु के स्वामित्व या आजीवन अर्थशास्त्र को नियंत्रित करने के लिए नीतियों का उपयोग किया जाता है। चूंकि मूल कोड में फ़ंक्शन सीधे पाइथन पर एक नया पॉइंटर लौटा रहा है, तो boost::python::manage_new_object उपयुक्त है यदि कॉलर से ऑब्जेक्ट को हटाने की ज़िम्मेदारी लेने की अपेक्षा की जाती है।

वस्तु प्रबंधन के लिए एक नीति को निर्दिष्ट करना अभी भी विफल:

#include <boost/python.hpp> 

int* make_int() { return new int(42); } 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::def("make_int", &make_int, 
    python::return_value_policy<python::manage_new_object>()); 
} 

निम्नलिखित प्रासंगिक उत्पादन का उत्पादन:

 
.../boost/python/object/make_instance.hpp:27:9: 
    error: no matching function for call to 'assertion_failed' 
    BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >)); 

इस मामले में, बूस्ट।पायथन हमें सूचित कर रहा है कि managed_new_object के साथ फ़ंक्शन से लौटाई गई वस्तु परिणाम परिणाम कनवर्टर जेनरेटर या तो class या union होना चाहिए। int* के लिए, सबसे उपयुक्त समाधान Boost.Python परत से गुजरते समय int पर मूल्य के अनुसार वापस करना है। हालांकि, पूर्णता के लिए, नीचे प्रदर्शित करता है:

  • विरासत API को अनुकूलित करने के लिए सहायक फ़ंक्शन का उपयोग करना।
  • पॉइंटर्स लौटने वाले फ़ैक्टरी फ़ंक्शन के साथ उपयोगकर्ता परिभाषित प्रकार के निर्माण को सीमित करने के लिए कैसे करें।
#include <boost/python.hpp> 

/// Legacy API. 
int* make_int() { return new int(42); } 

/// Auxiliary function that adapts the legacy API to Python. 
int py_make_int() 
{ 
    std::auto_ptr<int> ptr(make_int()); 
    return *ptr; 
} 

/// Auxiliary class that adapts the legacy API to Python. 
class holder 
    : private boost::noncopyable 
{ 
public: 
    holder() 
    : value_(make_int()) 
    {} 

    int get_value() const  { return *value_; } 
    void set_value(int value) { *value_ = value; } 

private: 
    std::auto_ptr<int> value_; 
}; 

/// Factory function for the holder class. 
holder* make_holder() 
{ 
    return new holder(); 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::def("make_int", &py_make_int); 

    python::class_<holder, boost::noncopyable>("Holder", python::no_init) 
    .add_property("value", 
     python::make_function(&holder::get_value), 
     python::make_function(&holder::set_value)) 
    ; 

    python::def("make_holder", &make_holder, 
    python::return_value_policy<python::manage_new_object>()); 
} 

इंटरएक्टिव उपयोग:

>>> import example 
>>> assert(42 == example.make_int()) 
>>> holder = example.Holder() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
RuntimeError: This class cannot be instantiated from Python 
>>> holder = example.make_holder() 
>>> assert(42 == holder.value) 
>>> holder.value *= 2 
>>> assert(84 == holder.value) 
+1

विस्तृत जवाब के लिए धन्यवाद! – avli

संबंधित मुद्दे