2013-07-31 5 views
0

템플릿 화 된 vistors을 사용하여 여러 클래스의 통합 인터페이스를 정의하고 있습니다. __str____repr__ 메서드를 정의하기 위해 boost::python::class 개체에서 프로그래밍 방식으로 클래스 이름 (참조 된 설명서에서 "X")을 얻고 싶습니다. 그게 가능하니?boost :: python :: class : 프로그래밍 방식으로 클래스 이름 얻기

클래스 이름을 방문자의 생성자에 인수로 전달하면 쉽게 처리 할 수 ​​있지만 자동으로 추가하면 더 우아 해집니다.

답변

5

boost::python::class_boost::python::object에서 파생되므로 클래스 개체에서 __name__ 특성을 쿼리 할 수 ​​있습니다.

#include <boost/python.hpp> 

class X {}; 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::object x_class = python::class_<X>("X"); 

    // Extract the class' __name__ attribute, printing whatever was passed to 
    // class_ constructor. 
    std::cout << boost::python::extract<std::string>(x_class.attr("__name__"))() 
      << std::endl; 
} 

그리고 출력 : 여기에

은 간단한 예입니다, boost::python::def_visitor에서 파생 방문자가 필요 하나

>>> import example 
X 

이 방법에 따라 확장하기로 :

  • 일반적으로을 반환하는 함수로 __str__ 및/또는 __repr__을 정의하십시오.의 클래스 이름은 o.__class__.__name__입니다.
  • 클래스 이름을 추출하고 저장 한 다음 저장된 값에 액세스하는 함수로 __str__ 및/또는 __repr__을 정의하십시오.

다음 예는이 두 방법을 모두 보여줍니다.

#include <boost/python.hpp> 

/// @brief Helper type used to set and get a boost::python::class_ 
///  object's type name. 
template <typename ClassT> 
class typed_class_name 
{ 
public: 
    /// @brief Extract and store the __name__ from a 
    ///  boost::python::class_ objct. 
    static void set(const ClassT& c) 
    { 
    name_ = boost::python::extract<std::string>(c.attr("__name__")); 
    } 

    /// @brief Return the stored name. 
    static std::string get(const typename ClassT::wrapped_type&) 
    { 
    std::cout << "typed" << std::endl; 
    return name_; 
    } 
private: 
    static std::string name_; 
}; 

template <typename ClassT> std::string typed_class_name<ClassT>::name_; 

/// @brief Generically get a python object's class name. 
struct generic_class_name 
{ 
    static boost::python::object get(const boost::python::object& self) 
    { 
    std::cout << "generic" << std::endl; 
    return self.attr("__class__").attr("__name__"); 
    } 
}; 

class my_def_visitor 
    : public boost::python::def_visitor<my_def_visitor> 
{ 
    friend class boost::python::def_visitor_access; 

    template <class ClassT> 
    void visit(ClassT& c) const 
    { 
    // Store the class name. 
    typed_class_name<ClassT>::set(c); 

    c 
     .def("__str__", &typed_class_name<ClassT>::get) // typed 
     .def("__repr__", &generic_class_name::get)  // generic 
     ; 
    } 
}; 

class X {}; 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::class_<X>("X") 
    .def(my_def_visitor()) 
    ; 
} 

그리고 사용 :

>>> import example 
>>> x = example.X() 
>>> str(x) 
typed 
'X' 
>>> repr(x) 
generic 
'X' 
+0

매우 포괄적 인 대답, 감사합니다! 나는'Python_AsString' 대신에'boost :: python :: extract (c.attr ("__ name __"))'을 사용할 것입니다. – eudoxos

+0

@ eudoxos : 좋은 지적입니다. Boost.Python의 추출기를 사용하기 위해 예제를 수정했습니다. Boost.Python의 'extract'는 함수가 아닌 유형이며, 'cout'에 삽입 할 때 명시적인 변환이 필요하다는 점을 잊어 버렸습니다. –