reference_existing_object option for pure_virtual c++ classes

Asked by sean ross

I am having trouble with the is_pure_virtual=True option. If I use a pointer as a parameter, to this function the copy constructor is used I would like to use something like reference_existing_object=True to avoid this.
for example.

PBG:
>>> NoddyClass.add_method( 'call_me', ReturnValue.new( 'float' ),
                [Parameter.new('const OtherClass*','n')],
                 is_pure_virtual=True )

The resulting output:

float
PyNoddy__PythonHelper::call_me(const OtherClass* n)
{
    ...

    py_OtherClass = PyObject_GC_New(PyOtherClass, &PyOtherClass_Type);
    py_OtherClass->inst_dict = NULL;
    py_OtherClass->flags = PYBINDGEN_WRAPPER_FLAG_NONE;

    // Problem
    py_OtherClass->obj = new OtherClass(*n);

    ...
}

What I would like to do is:

>>> NoddyClass.add_method( 'call_me', ReturnValue.new( 'float' ),
                [Parameter.new('const OtherClass*','n',reference_existing_object=True)],
                 is_pure_virtual=True )

output:

float
PyNoddy__PythonHelper::call_me(const OtherClass* n)
{
    ...

    py_OtherClass = PyObject_GC_New(PyOtherClass, &PyOtherClass_Type);
    py_OtherClass->inst_dict = NULL;
    py_OtherClass->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED;

    py_OtherClass->obj = n;

    ...
}

Is this possible? If it is not supported, what is the best workaround?

Thanks

Question information

Language:
English Edit question
Status:
Answered
For:
PyBindGen Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Launchpad Janitor (janitor) said :
#1

This question was expired because it remained in the 'Open' state without activity for the last 15 days.

Revision history for this message
Gustavo Carneiro (gjc) said :
#2

I suck. Sorry for not answering for so long.

Revision history for this message
Gustavo Carneiro (gjc) said :
#3

Nothing exactly like you want is currently supported. The closest thing is when the parameter is INOUT,

>>> NoddyClass.add_method( 'call_me', ReturnValue.new( 'float' ),
                [Parameter.new('const OtherClass*','n', Parameter.DIRECTION_INOUT)],
                 is_pure_virtual=True )

The resulting output is something like:

float
PyNoddy__PythonHelper::call_me(const OtherClass* n)
{
    ...

    py_OtherClass = PyObject_GC_New(PyOtherClass, &PyOtherClass_Type);
    py_OtherClass->inst_dict = NULL;
    py_OtherClass->flags = PYBINDGEN_WRAPPER_FLAG_NONE;

    // Problem
    py_OtherClass->obj = n;

    ...

    <<< PyObject_CallMethod(...) >>>

   if (py_OtherClass->ob_refcnt == 1) {
       py_OtherClass->obj = NULL;
   } else {
      py_OtherClass->obj = new OtherClass(*n);
   }
  ...
}

So basically it passes a reference to the original object, without copying, and after the call clears the object pointer in the wrapper if the python code hasn't kept a reference to the object, or makes another copy of the object if the python side wants to keep a reference.

If the OtherClass* n parameter is an object that was initially created by python side, then there is another option: wrapper registry. If a wrapper already exists for the object, and wrapper registry is activated (it isn't by default), then a reference to the existing wrapper is used and no object copy is performed (fallback code is written to create the object copy in case a wrapper is not registered yet).

To activate wrapper registry, add this line to your script before generating the code:

    pybindgen.settings.wrapper_registry = pybindgen.settings.StdMapWrapperRegistry

Can you help with this problem?

Provide an answer of your own, or ask sean ross for more information if necessary.

To post a message you must log in.