Menu

Using a custom shared_ptr class, recommendations?

Help
Dan
2016-05-11
2016-05-14
  • Dan

    Dan - 2016-05-11

    I'm working on a library that requires the use of a special shared_ptr class, currently I'm trying to make a custom object wrapper for that class.
    The wrapper looks like this:

            class EAGLEPYTHON_EXPORTS NodeWrapper: public QObject
            {
                Q_OBJECT
                public Q_SLOTS:
                    void delete_NodePtr(rcc::shared_ptr<EagleLib::Nodes::Node>* o);
                    QString GetName(rcc::shared_ptr<EagleLib::Nodes::Node>* node);
                    QString GetFullName(rcc::shared_ptr<EagleLib::Nodes::Node>* node);
                    QStringList ListParameters(rcc::shared_ptr<EagleLib::Nodes::Node>* node);
                    void AddNode(rcc::shared_ptr<EagleLib::Nodes::Node>* node, QString name);
            };
    

    and I register it like this:

    qRegisterMetaType<rcc::shared_ptr<EagleLib::Nodes::Node>>("NodePtr");
    PythonQt::self()->registerCPPClass("NodePtr", "", "EagleLib", PythonQtCreateObject<NodeWrapper>);
    

    Everything works correctly for accessing values, except delete_NodePtr is not called when I delete an object from inside of python.

    I'm using PythonQt from (https://github.com/Orochimarufan/PythonQt) and particularly the PyCPPWrapperExample.
    Any tips on fixing this?

    [edit]

    I should clarify that the shared pointer object is returned from a function in an object that is wrapped as follows:

    class EAGLEPYTHON_EXPORTS DataStreamWrapper: public QObject
            {
                Q_OBJECT
            public Q_SLOTS:
                void Step(DataStream* stream);
                void Play(DataStream* stream);
                void Pause(DataStream* stream);
                QStringList ListNodes(DataStream* stream);
                rcc::shared_ptr<EagleLib::Nodes::Node>* GetNode(DataStream* stream, QString name);
                rcc::shared_ptr<EagleLib::Nodes::Node>* GetNode(DataStream* stream, int index);
                void AddNode(DataStream* stream, QString name);
            };
    
     

    Last edit: Dan 2016-05-11
  • Florian Link

    Florian Link - 2016-05-12

    Hm, returning a pointer to a shared_ptr sound a bit fishy... You should probably return just a shared_ptr, without the star. I am also a bit confused by your naming. Shouldn't you typedef rcc::shared_ptr<EagleLib::Nodes::Node> to NodePtr and then use NodePtr* in your API? I don't see how the moc could understand that rcc::shared_ptr<EagleLib::Nodes::Node> is supposed to be a NodePtr... Regarding the delete, since you register your type as QMetaType, PythonQt probably calls the delete/destroy call on the QMetaType instead of your delete slot. But first I would try the typedef and use NodePtr throughout your API.

     
  • Dan

    Dan - 2016-05-14

    Hello and thank you for your response.
    I forgot that I tried that previously, but for sake of testing I'm willing to look at it again, maybe you can help me figure out what I did wrong.

    So I've typedefed as follows:

    typedef rcc::shared_ptr<EagleLib::Nodes::Node> NodePtr;
    

    I then have a class member function which returns a shared_ptr object:

    NodePtr GetNode(DataStream* stream, int index);
    

    Now in python I can get the node which returns a NodePtr object:

    node = stream.GetNode(0)
    type(node)
      <class 'PythonQt.EagleLib.NodePtr'>
    

    But when I try to access it, I get a read access violation:

    node.GetFullName() <-- from python
    
    this->refCount was 0xFFFFFFFFFFFFFFFFFFFF <-- C++ error
    

    Which is in the object's copy constructor.
    Which is called from this function:

    void EagleLib::python::wrappers::NodeWrapper::qt_static_metacall(QObject *_o,     QMetaObject::Call _c, int _id, void **_a)
    {
        if (_c == QMetaObject::InvokeMetaMethod) {
        NodeWrapper *_t = static_cast<NodeWrapper *>(_o);
        Q_UNUSED(_t)
        switch (_id) {
        case 0: _t->delete_NodePtr((*reinterpret_cast< NodePtr(*)>(_a[1]))); break;
        case 1: { QString _r = _t->GetName((*reinterpret_cast< NodePtr(*)>(_a[1])));
            if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = _r; }  break;
        case 2: { QString _r = _t->GetFullName((*reinterpret_cast< NodePtr(*)>(_a[1])));
            if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = _r; }  break;
        case 3: { QStringList _r = _t->ListParameters((*reinterpret_cast< NodePtr(*)>(_a[1])));
            if (_a[0]) *reinterpret_cast< QStringList*>(_a[0]) = _r; }  break;
        case 4: _t->AddNode((*reinterpret_cast< NodePtr(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        default: ;
            }
        }
    }
    

    Btw this is the new definition of NodeWrapper:

            class EAGLEPYTHON_EXPORTS NodeWrapper: public QObject
            {
                Q_OBJECT
                public Q_SLOTS:
                    void delete_NodePtr(NodePtr o);
                    QString GetName(NodePtr node);
                    QString GetFullName(NodePtr node);
                    QStringList ListParameters(NodePtr node);
                    void AddNode(NodePtr node, QString name);
            };
    
     

    Last edit: Dan 2016-05-14
    • Florian Link

      Florian Link - 2016-05-14

      In your class wrapper, you need to use a pointer to your typedef.

      void delete_NodePtr(NodePtr* o);
      

      and the same in all call arguments. This is the calling convention that
      PythonQt uses for wrapper slots.

      Regards,
      Florian

      On Saturday, 14 May 2016, Dan percocetpenguin@users.sf.net wrote:

      Hello and thank you for your response.
      I forgot that I tried that previously, but for sake of testing I'm willing
      to look at it again, maybe you can help me figure out what I did wrong.

      So I've typedefed as follows:

      typedef rcc::shared_ptr<EagleLib::Nodes::Node> NodePtr;
      

      I then have a class member function which returns a shared_ptr object:

      NodePtr GetNode(DataStream* stream, int index);
      

      Now in python I can get the node which returns a NodePtr object:

      node = stream.GetNode(0)
      type(node)
        <class 'PythonQt.EagleLib.NodePtr'>
      

      But when I try to access it, I get a read access violation:

      node.GetFullName()
      
      this->refCount was 0xFFFFFFFFFFFFFFFFFFFF
      

      Which is in the object's copy constructor.
      Which is called from this function:

      void
      

      EagleLib::python::wrappers::NodeWrapper::qt_static_metacall(QObject _o,
      QMetaObject::Call _c, int _id, void
      _a)
      {
      if (_c == QMetaObject::InvokeMetaMethod) {
      NodeWrapper
      _t = static_cast<NodeWrapper *="">(_o);
      Q_UNUSED(_t)
      switch (_id) {
      case 0: _t->delete_NodePtr((reinterpret_cast<
      NodePtr(
      )>(_a[1]))); break;
      case 1: { QString _r = _t->GetName((reinterpret_cast<
      NodePtr(
      )>(_a[1])));
      if (_a[0]) reinterpret_cast< QString>(_a[0]) = _r; } break;
      case 2: { QString _r = _t->GetFullName((reinterpret_cast<
      NodePtr(
      )>(_a[1])));
      if (_a[0]) reinterpret_cast< QString>(_a[0]) = _r; } break;
      case 3: { QStringList _r = _t->ListParameters((reinterpret_cast<
      NodePtr(
      )>(_a[1])));
      if (_a[0]) reinterpret_cast< QStringList>(_a[0]) = _r; }
      break;
      case 4: _t->AddNode((reinterpret_cast<
      NodePtr(
      )>(_a[1])),(reinterpret_cast< QString()>(_a[2]))); break;
      default: ;
      }
      }
      }

      Btw this is the new definition of NodeWrapper:

                          class EAGLEPYTHON_EXPORTS NodeWrapper: public
      

      QObject
      {
      Q_OBJECT
      public Q_SLOTS:
      void delete_NodePtr(NodePtr o);
      QString GetName(NodePtr node);
      QString GetFullName(NodePtr node);
      QStringList ListParameters(NodePtr
      node);
      void AddNode(NodePtr node, QString
      name);
      };


      Using a custom shared_ptr class, recommendations?


      Sent from sourceforge.net because you indicated interest in <
      https://sourceforge.net/p/pythonqt/discussion/631393/>

      To unsubscribe from further messages, please visit <
      https://sourceforge.net/auth/subscriptions/>

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.