Boost Python - C++ class' private static data blown away beforeaccessing in Python?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Stodge

    Boost Python - C++ class' private static data blown away beforeaccessing in Python?

    I've exposed a C++ class to Python using Boost Python. The class,
    let's say it's called Entity, contains private static data, which is
    an array of strings. Though I think it implements it using MFC's
    CPtrArray.

    I've also exposed a public function from Entity - let's say it's
    called foo. This function accesses the private static data (the string
    array).

    I have multiple instances of Entity stored in a custom C++ container,
    which is also exposed to Python as class EntityList.

    In Python, I retrive an Entity from the EntityList:

    elist = EntityList()
    elist.append(En tity())
    elist.append(En tity())

    entity = elist.get_at(0)

    entity.foo()

    But it crashes inside foo() as the private static data is empty; or
    rather the string array is empty. I know before that point that the
    private static data is valid when accessed earlier by the C++ code as
    the program works fine. It just won't work from Python, so somehow the
    private static data has been blown away but I can't work out where or
    why.

    The static data is setup at initialisation - my Python code is only
    called long after initialisation is complete.

    I added a static dump() function to the Entity class that dumps the
    string array, and even if I just do the following in Python:

    Entity.dump()

    in Python, the private static data is empty. Doing the same from C++
    works fine. Weird.

    I know this is an impossible question to ask, but can anyone think of
    something obvious I need to look into?

    Thanks
  • Giuseppe Ottaviano

    #2
    Re: Boost Python - C++ class' private static data blown away beforeaccessing in Python?

    >
    In Python, I retrive an Entity from the EntityList:
    >
    elist = EntityList()
    elist.append(En tity())
    elist.append(En tity())
    >
    entity = elist.get_at(0)
    >
    entity.foo()
    >
    But it crashes inside foo() as the private static data is empty; or
    rather the string array is empty. I know before that point that the
    private static data is valid when accessed earlier by the C++ code as
    the program works fine. It just won't work from Python, so somehow the
    private static data has been blown away but I can't work out where or
    why.
    Probably it is a problem of lifetime. What is the signature of append?
    Who deletes the appended Entity in C++ code?
    If append takes a raw pointer, Boost.Python copies the pointer but
    destroys the Entity object because it is a temporary and its reference
    count went to zero. So the pointer in the list is referring to a
    destroyed object, which results in undefined behaviour.

    Did you have a look at the lifetime policies of Boost.Python? The
    simplest way to workaround the problem is using const reference
    arguments, and always use value semantics. If it can result in a
    performance penalty, another simple way is using shared_ptr's, which
    have their own reference count (different from the one in CPython
    lib), but Boost.Python does the magic to make them work together.

    HTH,
    Giuseppe

    Comment

    • Stodge

      #3
      Re: Boost Python - C++ class' private static data blown away beforeaccessing in Python?

      Thanks. Maybe it's a DLL boundary issue? I'll look into this too.

      On Jul 5, 11:14 pm, Giuseppe Ottaviano <giu...@gmail.c omwrote:
      In Python, I retrive an Entity from the EntityList:
      >
      elist = EntityList()
      elist.append(En tity())
      elist.append(En tity())
      >
      entity = elist.get_at(0)
      >
      entity.foo()
      >
      But it crashes inside foo() as the private static data is empty; or
      rather the string array is empty. I know before that point that the
      private static data is valid when accessed earlier by the C++ code as
      the program works fine. It just won't work from Python, so somehow the
      private static data has been blown away but I can't work out where or
      why.
      >
      Probably it is a problem of lifetime. What is the signature of append?  
      Who deletes the appended Entity in C++ code?
      If append takes a raw pointer, Boost.Python copies the pointer but  
      destroys the Entity object because it is a temporary and its reference  
      count went to zero. So the pointer in the list is referring to a  
      destroyed object, which results in undefined behaviour.
      >
      Did you have a look at the lifetime policies of Boost.Python? The  
      simplest way to workaround the problem is using const reference  
      arguments, and always use value semantics. If it can result in a  
      performance penalty, another simple way is using shared_ptr's, which  
      have their own reference count (different from the one in CPython  
      lib), but Boost.Python does the magic to make them work together.
      >
      HTH,
      Giuseppe

      Comment

      • Stodge

        #4
        Re: Boost Python - C++ class' private static data blown away beforeaccessing in Python?

        I wonder if it's a DLL boundary problem.

        On Jul 5, 11:14 pm, Giuseppe Ottaviano <giu...@gmail.c omwrote:
        In Python, I retrive an Entity from the EntityList:
        >
        elist = EntityList()
        elist.append(En tity())
        elist.append(En tity())
        >
        entity = elist.get_at(0)
        >
        entity.foo()
        >
        But it crashes inside foo() as the private static data is empty; or
        rather the string array is empty. I know before that point that the
        private static data is valid when accessed earlier by the C++ code as
        the program works fine. It just won't work from Python, so somehow the
        private static data has been blown away but I can't work out where or
        why.
        >
        Probably it is a problem of lifetime. What is the signature of append?  
        Who deletes the appended Entity in C++ code?
        If append takes a raw pointer, Boost.Python copies the pointer but  
        destroys the Entity object because it is a temporary and its reference  
        count went to zero. So the pointer in the list is referring to a  
        destroyed object, which results in undefined behaviour.
        >
        Did you have a look at the lifetime policies of Boost.Python? The  
        simplest way to workaround the problem is using const reference  
        arguments, and always use value semantics. If it can result in a  
        performance penalty, another simple way is using shared_ptr's, which  
        have their own reference count (different from the one in CPython  
        lib), but Boost.Python does the magic to make them work together.
        >
        HTH,
        Giuseppe

        Comment

        • Stodge

          #5
          Re: Boost Python - C++ class' private static data blown away beforeaccessing in Python?

          Could it be a boundary problem? The static data is initialised by the
          application. The problem arises when the python module tries to access
          it.

          On Jul 5, 11:14 pm, Giuseppe Ottaviano <giu...@gmail.c omwrote:
          In Python, I retrive an Entity from the EntityList:
          >
          elist = EntityList()
          elist.append(En tity())
          elist.append(En tity())
          >
          entity = elist.get_at(0)
          >
          entity.foo()
          >
          But it crashes inside foo() as the private static data is empty; or
          rather the string array is empty. I know before that point that the
          private static data is valid when accessed earlier by the C++ code as
          the program works fine. It just won't work from Python, so somehow the
          private static data has been blown away but I can't work out where or
          why.
          >
          Probably it is a problem of lifetime. What is the signature of append?  
          Who deletes the appended Entity in C++ code?
          If append takes a raw pointer, Boost.Python copies the pointer but  
          destroys the Entity object because it is a temporary and its reference  
          count went to zero. So the pointer in the list is referring to a  
          destroyed object, which results in undefined behaviour.
          >
          Did you have a look at the lifetime policies of Boost.Python? The  
          simplest way to workaround the problem is using const reference  
          arguments, and always use value semantics. If it can result in a  
          performance penalty, another simple way is using shared_ptr's, which  
          have their own reference count (different from the one in CPython  
          lib), but Boost.Python does the magic to make them work together.
          >
          HTH,
          Giuseppe

          Comment

          • Stodge

            #6
            Re: Boost Python - C++ class' private static data blown away beforeaccessing in Python?

            Oops - I didn't see my post so I thought something had gone wrong and
            reposted. Apologies for the multiple posts.

            On Jul 9, 11:57 am, Stodge <sto...@gmail.c omwrote:
            Could it be a boundary problem? The static data is initialised by the
            application. The problem arises when the python module tries to access
            it.
            >
            On Jul 5, 11:14 pm, Giuseppe Ottaviano <giu...@gmail.c omwrote:
            >
            In Python, I retrive an Entity from the EntityList:
            >
            elist = EntityList()
            elist.append(En tity())
            elist.append(En tity())
            >
            entity = elist.get_at(0)
            >
            entity.foo()
            >
            But it crashes inside foo() as the private static data is empty; or
            rather the string array is empty. I know before that point that the
            private static data is valid when accessed earlier by the C++ code as
            the program works fine. It just won't work from Python, so somehow the
            private static data has been blown away but I can't work out where or
            why.
            >
            Probably it is a problem of lifetime. What is the signature of append?  
            Who deletes the appended Entity in C++ code?
            If append takes a raw pointer, Boost.Python copies the pointer but  
            destroys the Entity object because it is a temporary and its reference  
            count went to zero. So the pointer in the list is referring to a  
            destroyed object, which results in undefined behaviour.
            >
            Did you have a look at the lifetime policies of Boost.Python? The  
            simplest way to workaround the problem is using const reference  
            arguments, and always use value semantics. If it can result in a  
            performance penalty, another simple way is using shared_ptr's, which  
            have their own reference count (different from the one in CPython  
            lib), but Boost.Python does the magic to make them work together.
            >
            HTH,
            Giuseppe

            Comment

            Working...