diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 853932e..c92e40a 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -532,7 +532,9 @@ BOOST_PYTHON_MODULE( pykd ) .def( "asMap", &TypeInfo::asMap ) .def( "deref", &TypeInfo::deref ) .def( "__str__", &TypeInfo::print ) - .def( "__getattr__", &TypeInfo::getField ); + .def( "__getattr__", &TypeInfo::getField ) + .def("__len__", &TypeInfo::getElementCount ) + .def("__getitem__", &TypeInfo::getElementByIndex ); python::class_, boost::noncopyable >("typedVar", "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance", python::no_init ) diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 890e9a3..1faef89 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -213,14 +213,14 @@ std::string ArrayTypedVar::printValue() /////////////////////////////////////////////////////////////////////////////////// -TypedVarPtr ArrayTypedVar::getElementByIndex( ULONG index ) +python::object ArrayTypedVar::getElementByIndex( ULONG index ) { if ( index >= m_typeInfo->getCount() ) throw PyException( PyExc_IndexError, "Index out of range" ); TypeInfoPtr elementType = m_typeInfo->getElementType(); - return TypedVar::getTypedVar( m_client, elementType, m_varData->fork(elementType->getSize()*index) ); + return python::object( TypedVar::getTypedVar( m_client, elementType, m_varData->fork(elementType->getSize()*index) ) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -252,7 +252,7 @@ UdtTypedVar::getField( const std::string &fieldName ) /////////////////////////////////////////////////////////////////////////////////// -TypedVarPtr +python::object UdtTypedVar::getElementByIndex( ULONG index ) { TypeInfoPtr fieldType = m_typeInfo->getFieldByIndex(index); @@ -262,7 +262,9 @@ UdtTypedVar::getElementByIndex( ULONG index ) if ( fieldType->getStaticOffset() == 0 ) throw ImplementException( __FILE__, __LINE__, "Fix ME"); - return TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ); + return python::make_tuple( + m_typeInfo->getFieldNameByIndex(index), + TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ) ); } ULONG fieldOffset = fieldType->getOffset(); @@ -272,7 +274,9 @@ UdtTypedVar::getElementByIndex( ULONG index ) fieldOffset += getVirtualBaseDisplacement( fieldType ); } - return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ); + return python::make_tuple( + m_typeInfo->getFieldNameByIndex(index), + TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ) ); } /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 8c2ddc0..11211bb 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -64,11 +64,11 @@ public: throw PyException( PyExc_TypeError, "object has no len()" ); } - virtual TypedVarPtr getElementByIndex( ULONG index ) { + virtual python::object getElementByIndex( ULONG index ) { throw PyException( PyExc_TypeError, "object is unsubscriptable"); } - TypedVarPtr getElementByIndexPtr( const TypedVarPtr& tv ) { + python::object getElementByIndexPtr( const TypedVarPtr& tv ) { return getElementByIndex( boost::apply_visitor( VariantToULong(), tv->getValue() ) ); } @@ -158,7 +158,7 @@ public: virtual std::string printValue(); - virtual TypedVarPtr getElementByIndex( ULONG index ); + virtual python::object getElementByIndex( ULONG index ); }; /////////////////////////////////////////////////////////////////////////////////// @@ -184,7 +184,7 @@ protected: return m_typeInfo->getFieldCount(); } - virtual TypedVarPtr getElementByIndex( ULONG index ); + virtual python::object getElementByIndex( ULONG index ); LONG getVirtualBaseDisplacement( TypeInfoPtr& typeInfo ); }; diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index 320b545..ecc8b7a 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -128,6 +128,14 @@ public: throw TypeException( getName(), "type is not a pointer" ); } + virtual ULONG getElementCount() { + throw PyException( PyExc_TypeError, "object has no len()" ); + } + + virtual python::tuple getElementByIndex( ULONG index ) { + throw PyException( PyExc_TypeError, "object is unsubscriptable"); + } + void setOffset( ULONG offset ) { m_offset = offset; } @@ -309,6 +317,14 @@ protected: return true; } + virtual ULONG getElementCount() { + return getFieldCount(); + } + + virtual python::tuple getElementByIndex( ULONG index ) { + return python::make_tuple( getFieldNameByIndex(index), getFieldByIndex(index) ); + } + virtual std::string print(); pyDia::SymbolPtr m_dia; diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index b8a382b..e290126 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -258,6 +258,8 @@ class TypedVarTest( unittest.TestCase ): def testUdtSubscribe(self): tv = pykd.typedVar( "g_virtChild" ) self.assertEqual( 5, len(tv) ) - self.assertEqual( tv[4], tv.m_baseField ) + fieldName, fieldVal = tv[4] + self.assertEqual( fieldName, "m_baseField" ) + self.assertEqual( fieldVal, tv.m_baseField ) for field in tv: str( field ) diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 149cfe6..82f1be7 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -185,3 +185,9 @@ class TypeInfoTest( unittest.TestCase ): self.assertNotEqual( 0, ti.m_staticConst.offset() ) self.assertNotEqual( 0, ti.m_stdstr.offset() ) + def testUdtSubscribe(self): + tv = pykd.typeInfo( "g_virtChild" ) + self.assertEqual( 5, len(tv) ) + for field in tv: + str( field ) +