Python embedded in C++ try_rich_compare error on types
Question: I have an error in my program, which appears to be something to do with
comparing two object types in python. Here is the error from gdb

    
    
        Program received signal SIGSEGV, Segmentation fault.
    0x00007fffc3acd35c in try_rich_compare (v=0x7fffcc433ec0 <UTOPIA::PyNodeType>, w=0x7fffc3a06ec0 <UTOPIA::PyNodeType>, op=3) at ../Objects/object.c:621
    621 ../Objects/object.c: No such file or directory.
    (gdb) bt
    #0  0x00007fffc3acd35c in try_rich_compare (v=0x7fffcc433ec0 <UTOPIA::PyNodeType>, w=0x7fffc3a06ec0 <UTOPIA::PyNodeType>, op=3) at ../Objects/object.c:621
    #1  0x00007fffc3acded7 in do_richcmp (v=0x7fffcc433ec0 <UTOPIA::PyNodeType>, w=0x7fffc3a06ec0 <UTOPIA::PyNodeType>, op=3) at ../Objects/object.c:930
    #2  0x00007fffc3ace164 in PyObject_RichCompare (v=0x7fffcc433ec0 <UTOPIA::PyNodeType>, w=0x7fffc3a06ec0 <UTOPIA::PyNodeType>, op=3) at ../Objects/object.c:982
    #3  0x00007fffc3b74a24 in cmp_outcome (op=3, v=0x7fffcc433ec0 <UTOPIA::PyNodeType>, w=0x7fffc3a06ec0 <UTOPIA::PyNodeType>) at ../Python/ceval.c:4525
    #4  0x00007fffc3b6bbbe in PyEval_EvalFrameEx (f=0x157e990, throwflag=0) at ../Python/ceval.c:2287
    #5  0x00007fffc3b6ff3e in PyEval_EvalCodeEx (co=0x7fffc2553510, globals=0x7fffc254b1a8, locals=0x0, args=0x7fffc257c6a0, argcount=2, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0)
    at ../Python/ceval.c:3252
    #6  0x00007fffc3aa643b in function_call (func=0x7fffc2552300, arg=0x7fffc257c678, kw=0x0) at ../Objects/funcobject.c:526
    #7  0x00007fffc3a64c79 in PyObject_Call (func=0x7fffc2552300, arg=0x7fffc257c678, kw=0x0) at ../Objects/abstract.c:2529
    #8  0x00007fffc3a810a1 in instancemethod_call (func=0x7fffc2552300, arg=0x7fffc257c678, kw=0x0) at ../Objects/classobject.c:2602
    #9  0x00007fffc3a64c79 in PyObject_Call (func=0x7fffd80df5e0, arg=0x7fffc2550370, kw=0x0) at ../Objects/abstract.c:2529
    #10 0x00007fffc3a64de1 in call_function_tail (callable=0x7fffd80df5e0, args=0x7fffc2550370) at ../Objects/abstract.c:2561
    #11 0x00007fffc3a651f3 in PyObject_CallMethod (o=0x7fffc255ced0, name=0x7fffcc4659a4 "invoke", format=0x7fffcc4659a2 "O") at ../Objects/abstract.c:2638
    #12 0x00007fffcc45d556 in UTOPIA::Python_service_interface::invoke (this=0x14ed610, invocation_=0x16aa6f0, input_=...)
    at /home/oni/Projects/utopia/components/libutopia/plugins/python/service_interface.cpp:134
    

My program contains a library of objects. Some of these objects are wrapped
inside a python object wrapper. My main C++ program loads this python library
in order to get the definitions of these types. In this case, the offending
type looks like this:

    
    
     // Node class
        static PyTypeObject PyNodeType =
        {
            PyObject_HEAD_INIT(0)
            0,                                 /* ob_size */
            "utopia.Node",                     /* tp_name */
            sizeof(PyNode),                    /* tp_basicsize */
            0,                                 /* tp_itemsize */
            (destructor) PyNode_dealloc,       /* tp_dealloc */
            0,                                 /* tp_print */
            0,                                 /* tp_getattr */
            0,                                 /* tp_setattr */
            0,                                 /* tp_compare */
            (reprfunc) PyNode_repr,            /* tp_repr */
            0,                                 /* tp_as_number */
            0,                                 /* tp_as_sequence */
            &PyNode_as_mapping,                /* tp_as_mapping */
            0,                                 /* tp_hash  */
            0,                                 /* tp_call */
            0,                                 /* tp_str */
            0,                                 /* tp_getattro */
            0,                                 /* tp_setattro */
            0,                                 /* tp_as_buffer */
            Py_TPFLAGS_DEFAULT,                /* tp_flags */
            "UTOPIA::GenericNode class",       /* tp_doc */
            0,                                 /* tp_traverse */
            0,                                 /* tp_clear */
            0,                                 /* tp_richcompare */
            0,                                 /* tp_weaklistoffset */
            0,                                 /* tp_iter */
            0,                                 /* tp_iternext */
            PyNode_methods,                    /* tp_methods */
            0,                                 /* tp_members */
            0,                                 /* tp_getset */
            0,                                 /* tp_base */
            0,                                 /* tp_dict */
            0,                                 /* tp_descr_get */
            0,                                 /* tp_descr_set */
            0,                                 /* tp_dictoffset */
            (initproc) PyNode_init,            /* tp_init */
            0,                                 /* tp_alloc */
            PyNode_new,                        /* tp_new */
            0,                                 /* tp_free */
            0,                                 /* tp_is_gc */
            0,                                 /* tp_bases */
            0,                                 /* tp_mro */
            0,                                 /* tp_cache */
            0,                                 /* tp_subclasses */
            0,                                 /* tp_weaklist */
            0,                                 /* tp_del */
        };
    

Now, later on, the C++ program loads the python2.7 library and launches python
inside itself. It then imports this wrapper python library.

This means this PyNodeType appears in the C++ program and also inside the
python instance running inside the c++ program. At some point, these two
things are compared and the program blows up! :S

Not really sure how to get around this one as the definition is needed in both
places.

Further inspection reveals that, while the type is somehow deduced, one of
these parameters is full of null pointers

    
    
    (gdb) print v
    $4 = (PyObject *) 0x7fffcc433ec0 <UTOPIA::PyNodeType>
    (gdb) print *v
    $5 = {_ob_next = 0x0, _ob_prev = 0x0, ob_refcnt = 2, ob_type = 0x0}
    (gdb) print *w
    $6 = {_ob_next = 0x7fffd80b3310, _ob_prev = 0x7fffe00aca70, ob_refcnt = 43, ob_type = 0x7fffc3efc0c0 <PyType_Type>}
    

*****UPDATE*****

So When I create an object I take a look at the memory locations

    
    
    PyNode* newPyNode = PyObject_New(PyNode, &PyNodeType);
    (gdb) print &PyNodeType
    $4 = (PyTypeObject *) 0x7fffe353cea0 <UTOPIA::PyNodeType>
    

But then, if I look at the ob_type field in my newPyNode object

    
    
    (gdb) print *newPyNode
    $7 = {_ob_next = 0x7fffe12fd1c8, _ob_prev = 0x7fffe32024e0 <refchain>, ob_refcnt = 1, ob_type = 0x7fffe2a10ec0 <UTOPIA::PyNodeType>, node = 0xef2cc0}
    

ob_type does not match. What gives? Looking at the comparison functions like

    
    
    PyObject_TypeCheck
    

... these memory locations should be the same.


Answer: Looks like its fixed. Ive joined together the CPP .so part of the project with
the python library.so which seems to have fixed the problem. The former .so
was so the main project could load python scripts whilst the second was to
allow a python program access to all the utopia functionality (the opposite in
effect). Joining the two libs together appears to have fixed it.

