2014-06-10 3 views
0

파이썬에서 기본 형식 (예 : int 또는 double)의 shared_ptr을 사용하려고하는데 파이썬으로 내보내는 방법을 모르겠습니다.기본 형식의 shared_ptr을 파이썬으로 내보내는 방법

나는 다음과 같은 클래스가 : 클래스는 이런 방식으로 수출되고있다

class Holder 
{ 
public: 
    Holder(int v) : value(new int(v)) {}; 
    boost::shared_ptr<int> value; 
}; 

: 파이썬 코드에서

class_<Holder>("Holder", init<int>()) 
    .def_readwrite("value", &Holder::value); 

, 나는 "홀더 인스턴스 .value"를 설정하기 위해 노력하고있어 이미 사용중인 인스턴스를 사용하여 존재합니다.

h1 = mk.Holder(10) 
h2 = mk.Holder(20) 
h1.value = h2.value 

다음 발생했습니다 :

TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<int> 

내 질문은 : 어떻게 파이썬 boost::shared_ptr<int>를 내보낼 수 있습니다?

+0

는 의미의 어떤 종류가 필요합니까? 위의 예제를 계속하면, 정수 값을'h1.value'에 할당하여'h2.value'에 반영시킬 수있을 것으로 기대합니까? 이'x = h1.value; x = 42' ...'h2.value'는 그 문장 다음에 어떤 식 으로든'42'로 평가해야합니까? 여러분이 묻는 것은 파이썬에서 그레인에 대해 조금 있지만 우리는 아마 합당한 답을 찾을 수 있습니다. – abingham

답변

1

또 다른 유형과 동일한 방식으로 파이썬 boost::shared_ptr<int> 수출 boost::python::class_를 사용할 수 있습니다

boost::python::class_<boost::shared_ptr<int> >(...); 

그러나, shared_ptr를 노출 할 때 도입 된 의미에주의하십시오.예를 들어, 다른 Holder.value 단순히 boost::shared_ptr<int>의 할당 연산자를 호출 한 Holder.value에 할당하는 경우를 고려하고, Holder.increment()int 오히려 새로운 intvalue 지점을하는 것보다 value 가리키는 조작 :

h1 = Holder(10) 
h2 = Holder(20) 
h1.value = h2.value # h1.value and h2.value point to the same int. 
h1.increment() # Change observed in h2.value. The semantics may be unexpected 
       # by Python developers. 

다음은 원래 코드를 기반으로 boost::shared_ptr<int>을 표시하는 완전한 예입니다.

#include <sstream> 
#include <string> 
#include <boost/python.hpp> 
#include <boost/shared_ptr.hpp> 

class Holder 
{ 
public: 
    Holder(int v) 
    : value(new int(v)) 
    {}; 

    boost::shared_ptr<int> value; 
}; 

std::string holder_value_str(const boost::shared_ptr<int>& value) 
{ 
    std::stringstream stream; 
    stream << value.get() << " contains " << *value; 
    return stream.str(); 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    { 
    python::scope holder = python::class_<Holder>(
     "Holder", python::init<int>()) 
     .def_readwrite("value", &Holder::value) 
     ; 

    // Holder.Value 
    python::class_<boost::shared_ptr<int> >("Value", python::no_init) 
     .def("__str__", &holder_value_str) 
     ; 
    } 
} 

대화 형 사용 : 하나 고려하면

>>> import example 
>>> h1 = example.Holder(10) 
>>> h2 = example.Holder(20) 
>>> print h1.value 
0x25f4bd0 contains 10 
>>> print h2.value 
0x253f220 contains 20 
>>> h1.value = h2.value 
>>> print h1.value 
0x253f220 contains 20 

또는 shared_ptr는 C++ 메모리 관리 프록시에 지나지으로, 다음은 Holder::value이 경우에도, 파이썬의 intHolder.value를 노출하는 것이 합리적 일 수있다 boost::shared_ptr<int>. 이것은 파이썬 개발자에게 예상되는 의미와 허가 문을 제공 할 것이다. h1.value = h2.value + 5. 여기에 대신 boost::shared_ptr<int> 유형을 노출의 int에서 Holder::value를 변환하는 보조 기능을 사용하는 예는 다음과 같습니다

#include <boost/python.hpp> 
#include <boost/shared_ptr.hpp> 

class Holder 
{ 
public: 
    Holder(int v) 
    : value(new int(v)) 
    {}; 

    boost::shared_ptr<int> value; 
}; 

/// @brief Auxiliary function used to get Holder.value. 
int get_holder_value(const Holder& self) 
{ 
    return *(self.value); 
} 

/// @brief Auxiliary function used to set Holder.value. 
void set_holder_value(Holder& self, int value) 
{ 
    *(self.value) = value; 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::scope holder = python::class_<Holder>(
     "Holder", python::init<int>()) 
    .add_property("value", 
     python::make_function(&get_holder_value), 
     python::make_function(&set_holder_value)) 
    ; 
} 

대화 형 사용 :

>>> import example 
>>> h1 = example.Holder(10) 
>>> h2 = example.Holder(20) 
>>> assert(h1.value == 10) 
>>> assert(h2.value == 20) 
>>> h1.value = h2.value 
>>> assert(h1.value == 20) 
>>> h1.value += 22 
>>> assert(h1.value == 42) 
>>> assert(h2.value == 20) 
1

필요하십니까? 파이썬은 자신의 참조 카운팅 메카니즘을 가지고 있으며, 그것을 사용하는 것이 더 간단 할 수도 있습니다. (그러나 많은 은 C++ 측에서 어떤 일이 일어나고 있는지에 달려 있습니다.)

그렇지 않으면 공유 포인터가 들어있는 파이썬 객체를 으로 정의해야합니다. 그냥 같은 정의 :이 비교적 간단

struct PythonWrapper 
{ 
    PyObject_HEAD 
    boost::shared_ptr<int> value; 
    // Constructors and destructors can go here, to manage 
    // value. 
}; 

을 그리고 선언하고 다른 객체 것처럼 관리; 단지 당신은 유형의 객체가 이다 창조 할 때 new 할 수 있는지 확인합니다 (그리고 그들은 당신이, 파이썬에 제공하는 기능을 만들어야합니다 경우 tp_new 필드에서 함수에서 아무것도), 및 기능에 delete 등록한 객체 타입의 tp_dealloc 필드 을 넣습니다.