Skip to content

How do I use cppyy with a class that has overloaded operator-> #295

@RochaStratovan

Description

@RochaStratovan

I am working with an SDK that has a class that overloaded operator->. Can cppyy work with this?

I reviewed the documentation for class operators. I see

Image


which made me think I might use foo.__deref__() or foo.__follow__().

TLDR:
Using __follow__() or __deref__() causes a segmentation violation crash.

This is an example of the python logic I've written for this

Logic
def OnReceiveDicosFileAIT3D(
        self,
        ait: SDICOS.Utils.DicosData[SDICOS.AIT3D],
        errorlog: SDICOS.ErrorLog) -> None:
    stvnDebug(f"{self.__class__} AIT3D")

    print(f"{self.__class__} AIT3D")
    print(f"ait: {type(ait)}", flush=True)

    local_ait = SDICOS.AIT3D()
    print(f"local object: {type(local_ait)}", flush=True)

    print(f"About to deref", flush=True)
    local_ait = ait.__deref__()
    print(f"Defef done, about to use object", flush=True)
    print(f"deref object:  {type(local_ait)}", flush=True)

This is an example of the output and failure that is observed

Output
# This output is from an chunk of python code that isn't shown. It provides
# details about the file being loaded.
#
Loading AIT3D files with:
 OOI ID:              200
 Scan Instance UID:   1569373546.53567.20144.131247.1016416342191116
 Series Instance UID: 1844515061.54828.17037.179177.7621782279319
 SOP Class UID:       1.2.840.10008.5.1.4.1.1.501.5
<class '__main__.DicosLoadingCallback'>
message type '<class cppyy.gbl.SDICOS.Utils.DicosData<SDICOS::AIT3D> at 0x2dd8bfd0>' received'

# Output from the python method shared above
#
<class '__main__.DicosLoadingCallback'> AIT3D
ait: <class cppyy.gbl.SDICOS.Utils.DicosData<SDICOS::AIT3D> at 0x2dd8bfd0>
local object: <class cppyy.gbl.SDICOS.AIT3D at 0x2ddc3850>
About to deref


*** Break *** segmentation violation
#0  0x00007f547e6a2c3a in __GI___wait4 (pid=135891, stat_loc=stat_loc
entry=0x7ffd72487f48, options=options
entry=0, usage=usage
entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:27
#1  0x00007f547e6a2bfb in __GI___waitpid (pid=<optimized out>, stat_loc=stat_loc
entry=0x7ffd72487f48, options=options
entry=0) at waitpid.c:38
#2  0x00007f547e611f67 in do_system (line=<optimized out>) at ../sysdeps/posix/system.c:172
#3  0x00007f547d7b7c65 in CppyyLegacy::TUnixSystem::StackTrace() () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#4  0x00007f54769ebcf2 in (anonymous namespace)::do_trace (sig=1) at src/clingwrapper.cxx:267
#5  (anonymous namespace)::TExceptionHandlerImp::HandleException (this=<optimized out>, sig=1) at src/clingwrapper.cxx:280
#6  0x00007f547d7b6741 in CppyyLegacy::TUnixSystem::DispatchSignals(CppyyLegacy::ESignals) () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#7  <signal handler called>
#8  0x00007f547d79147c in CppyyLegacy::TIsAProxy::operator()(void const*) () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#9  0x00007f547d77bfdb in CppyyLegacy::TClass::GetActualClass(void const*) const () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#10 0x00007f54769fb854 in Cppyy::GetActualClass (klass=klass
entry=41, obj=obj
entry=0x7f5473d565d2 <SDICOS::Network::IDcsServerImpl::DcsSocketSession::OnGetApplicationContextName() const>) at /tmp/pip-build-env-bi7oals9/overlay/lib/python3.13/site-packages/cppyy_backend/include/TClassRef.h:75
#11 0x00007f5474890805 in CPyCppyy::BindCppObject (address=address
entry=0x7f5473d565d2 <SDICOS::Network::IDcsServerImpl::DcsSocketSession::OnGetApplicationContextName() const>, klass=klass
entry=41, flags=flags
entry=0) at src/ProxyWrappers.cxx:931
#12 0x00007f54748774e3 in CPyCppyy::(anonymous namespace)::InstanceRefExecutor::Execute (this=0x2ea59590, method=<optimized out>, self=<optimized out>, ctxt=0x7ffd7248ab50) at src/CallContext.h:102
#13 0x00007f5474831cd9 in CPyCppyy::CPPMethod::ExecuteFast (this=<optimized out>, self=<optimized out>, offset=<optimized out>, ctxt=0x7ffd7248ab50) at src/CPPMethod.cxx:123
#14 0x00007f547482ff25 in CPyCppyy::CPPMethod::Execute (this=0x2dbd96d0, self=<optimized out>, offset=<optimized out>, ctxt=<optimized out>) at src/CPPMethod.cxx:970
#15 0x00007f547483005f in CPyCppyy::CPPMethod::Call (this=0x2dbd96d0, self=
0x7ffd7248aae8: 0x7f54727ae890, args=<optimized out>, nargsf=<optimized out>, kwds=<optimized out>, ctxt=0x7ffd7248ab50) at src/CPPMethod.cxx:1023
#16 0x00007f5474835b9f in CPyCppyy::(anonymous namespace)::mp_vectorcall (pymeth=0x7f54727ad500, args=0x7f547e7bf410, nargsf=<optimized out>, kwds=0x0) at /usr/include/python3.13/object.h:949
#17 0x0000000000686d76 in PyObject_Vectorcall ()
#18 0x00000000005c549f in _PyEval_EvalFrameDefault ()
#19 0x00000000006843ce in ?? ()
#20 0x00000000006864fe in ?? ()
#21 0x0000000000686850 in PyObject_CallMethodObjArgs ()
#22 0x00007f54727642a6 in ?? ()
#23 0x00007ffd7248b240 in ?? ()
#24 0x00007f54727ae8d0 in ?? ()
#25 0x0000000000000016 in ?? ()
#26 0x0000000000000016 in ?? ()
#27 0x000000770000006a in ?? ()
#28 0x0000000000000000 in ?? ()
 *** Break *** segmentation violation
#0  0x00007f547e6a2c3a in __GI___wait4 (pid=136031, stat_loc=stat_loc
entry=0x7ffd72487f48, options=options
entry=0, usage=usage
entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:27
#1  0x00007f547e6a2bfb in __GI___waitpid (pid=<optimized out>, stat_loc=stat_loc
entry=0x7ffd72487f48, options=options
entry=0) at waitpid.c:38
#2  0x00007f547e611f67 in do_system (line=<optimized out>) at ../sysdeps/posix/system.c:172
#3  0x00007f547d7b7c65 in CppyyLegacy::TUnixSystem::StackTrace() () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#4  0x00007f54769ebb7e in (anonymous namespace)::do_trace (sig=1) at src/clingwrapper.cxx:267
#5  (anonymous namespace)::TExceptionHandlerImp::HandleException (this=<optimized out>, sig=1) at src/clingwrapper.cxx:286
#6  0x00007f547d7b6741 in CppyyLegacy::TUnixSystem::DispatchSignals(CppyyLegacy::ESignals) () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#7  <signal handler called>
#8  0x00007f547d79147c in CppyyLegacy::TIsAProxy::operator()(void const*) () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#9  0x00007f547d77bfdb in CppyyLegacy::TClass::GetActualClass(void const*) const () from /home/stratarocha/Desktop/cppyyDICOS/WORK/lib/python3.13/site-packages/cppyy_backend/lib/libCoreLegacy.so
#10 0x00007f54769fb854 in Cppyy::GetActualClass (klass=klass
entry=41, obj=obj
entry=0x7f5473d565d2 <SDICOS::Network::IDcsServerImpl::DcsSocketSession::OnGetApplicationContextName() const>) at /tmp/pip-build-env-bi7oals9/overlay/lib/python3.13/site-packages/cppyy_backend/include/TClassRef.h:75
#11 0x00007f5474890805 in CPyCppyy::BindCppObject (address=address
entry=0x7f5473d565d2 <SDICOS::Network::IDcsServerImpl::DcsSocketSession::OnGetApplicationContextName() const>, klass=klass
entry=41, flags=flags
entry=0) at src/ProxyWrappers.cxx:931
#12 0x00007f54748774e3 in CPyCppyy::(anonymous namespace)::InstanceRefExecutor::Execute (this=0x2ea59590, method=<optimized out>, self=<optimized out>, ctxt=0x7ffd7248ab50) at src/CallContext.h:102
#13 0x00007f5474831cd9 in CPyCppyy::CPPMethod::ExecuteFast (this=<optimized out>, self=<optimized out>, offset=<optimized out>, ctxt=0x7ffd7248ab50) at src/CPPMethod.cxx:123
#14 0x00007f547482ff25 in CPyCppyy::CPPMethod::Execute (this=0x2dbd96d0, self=<optimized out>, offset=<optimized out>, ctxt=<optimized out>) at src/CPPMethod.cxx:970
#15 0x00007f547483005f in CPyCppyy::CPPMethod::Call (this=0x2dbd96d0, self=
0x7ffd7248aae8: 0x7f54727ae890, args=<optimized out>, nargsf=<optimized out>, kwds=<optimized out>, ctxt=0x7ffd7248ab50) at src/CPPMethod.cxx:1023
#16 0x00007f5474835b9f in CPyCppyy::(anonymous namespace)::mp_vectorcall (pymeth=0x7f54727ad500, args=0x7f547e7bf410, nargsf=<optimized out>, kwds=0x0) at /usr/include/python3.13/object.h:949
#17 0x0000000000686d76 in PyObject_Vectorcall ()
#18 0x00000000005c549f in _PyEval_EvalFrameDefault ()
#19 0x00000000006843ce in ?? ()
#20 0x00000000006864fe in ?? ()
#21 0x0000000000686850 in PyObject_CallMethodObjArgs ()
#22 0x00007f54727642a6 in ?? ()
#23 0x00007ffd7248b240 in ?? ()
#24 0x00007f54727ae8d0 in ?? ()
#25 0x0000000000000016 in ?? ()
#26 0x0000000000000016 in ?? ()
#27 0x000000770000006a in ?? ()
#28 0x0000000000000000 in ?? ()
(WORK) 

It appears that the __deref__() call is what fails. The same sort of failure occurs if I attempt to use __follow__()

The relevant part of the C++ header file is shown below. The DicosData class
appears to be a generic data wrapper that provides various generic bits of
functionality, but then the specific data can be obtained with operator-> or
operator*

C++ API logic
     /// \class DicosData
     /// \brief Structure for holding DICOS used in callback functions.
     /// Data can be moved out of this object.
     template< typename TYPE >
     class DicosData : public DicosDataBase
     {
     public:
         /// Constructor
         DicosData(): DicosDataBase()...

         /// Destructor
         ~DicosData()    {FreeMemory();}
  
         ...
         
  
         /// Returns pointer to TYPE data
         TYPE* operator->()              {return m_pdata;}
         
         /// Returns pointer to TYPE data
         const TYPE* operator->()const   {return m_pdata;}
  
         /// Returns reference to TYPE data
         TYPE& operator*()               {return *m_pdata;}
         
         /// Returns reference to TYPE data
         const TYPE& operator*()const    {return *m_pdata;}

     private:    
         /// Disable copy constructor
         DicosData(DicosData &)                  {S_ASSERT(0);}

         /// Disable copy operator
         DicosData& operator=(const DicosData &rhs)  
         {
             if(this == &rhs)
             {
             return *this;
             }
             
             S_ASSERT(0); 
             return *this;
         }

         TYPE*       m_pdata;        ///< DICOS data for callback functions
  
         /// Original data in Tag-Level API if not using Tag-Level API. If
         /// data comes from disk, then the file names are stored with the
         /// original data. If data comes from network transmission, then the
         /// file name is left empty.
         /// The original data excludes the pixel data to prevent duplication
         // of potentially very large data.
         Array1D< std::pair<SDICOS::Filename, SDICOS::AttributeManager*> >   m_vpOriginal;
     };
Environment
OS Ubuntu 20.04.6
Python Version 3.13.2 - using venv
Cppyy Vesion 3.5.0 - using venv, installed with sudo apt

Any documentation or advice you can point me to for this challenge?

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions