dlr-gtlab / python-module

GTlab Module for embadding Python into GTlab
0 stars 0 forks source link

Cannot call shared function that takes a GtObject* as an argument #259

Closed rainman110 closed 4 months ago

rainman110 commented 9 months ago

In GitLab by @mariusalexander on Feb 9, 2024, 10:02

Steps to reproduce

1) Implement shared fucntion that takes a GtObject* as an argument

QList<gt::SharedFunction>
GtIntelliGraphModule::sharedFunctions() const
{
    QList<gt::SharedFunction> list;

    auto func = [](GtObject* obj){
        gtDebug() << obj->objectName();
    };

    list << gt::interface::makeSharedFunction("my_function", func);

    return list;
}

2) Call function using Python API

grafik

rainman110 commented 8 months ago

I first analysis of the code reveals the following.

  1. All arguments are casted by PythonQT to QVariant
  2. While casting, it compares the python type with predefined types.
  3. Since GTObject are a special object , python qt does not know how to convert it

The reason is, that @marvinoe21 decided to wrap GTobjects in a special type "GtpyExtendedWrapper", which is unfortunately not derived from PythonQt.PythonQtInstanceWrapper, but uses it by composition.

If it would be a normal Qt type in the python type system, it would work.

To test this, I added a method toQObject, which converts a GTObject into the PythonQt type system.

Here's the demo

GTlab> pro = currentProject()
GTlab> f = shared_function("Python Module (Python 3.12)", "get_object_name")

GTlab> f(pro)
('unknown',)

GTlab> f(pro.toQObject())
('PERFECT-UHBR-GTF_upgraded',)

@mariusalexander + @marvinoe21 We could use the .toQObject() method as a workaround. Ideally though, we should change the extended wrapper to derive from the PythonQt basetype. @marvinoe21 Is there any reason, why it was not derived from in the first place?

rainman110 commented 8 months ago

In GitLab by @mariusalexander on Mar 5, 2024, 15:35

Would it be possible to convert the GtpyExtendedWrapper into a GtObject*/QObject when calling the shared function? (Without us having to call to toQObject)

rainman110 commented 8 months ago

I suppose that would work... I am not yet very deep into the python module though.

rainman110 commented 8 months ago

It works, I actually found a working code for it inside the python module:

    if (PyPPTuple_Check(args))
    {
        int size = PyPPTuple_Size(args);

        for (int i = 0; i < size; i++)
        {
            auto arg = PyPPTuple_GetItem(args, i);

            if (!arg || !PyPPObject_TypeCheck(arg, &GtpyExtendedWrapper_Type)) continue;

            GtpyExtendedWrapper* wrapper = (GtpyExtendedWrapper*)arg.get();
            auto wrappedObj = PyPPObject::Borrow((PyObject*)wrapper->_obj);
            PyPPTuple_SetItem(args, i, std::move(wrappedObj));

        }
    }
rainman110 commented 8 months ago

This basically replaces the extended type by the base type.

rainman110 commented 8 months ago

In GitLab by @mariusalexander on Mar 6, 2024, 07:33

Awesome, sounds good! I suppose let's wait for @marvinoe21? :)

rainman110 commented 8 months ago

mentioned in commit 4195ace72b5e80f86e3b4a70ed859719f377472a

rainman110 commented 8 months ago

mentioned in commit 433cc511aca8a7c96f8432dc57c0e269d8935483

rainman110 commented 8 months ago

mentioned in commit a5fdbee97e385fa50230b5d13813df234e612a3a

rainman110 commented 8 months ago

mentioned in commit d62120a0d7b2b3fe1c74e8b68dad46b828879462

rainman110 commented 8 months ago

mentioned in commit 17787a89e7f460a22c7d972c60727c2b2dc3e704

rainman110 commented 8 months ago

mentioned in commit b17fadae255891324e631dd2b09658d36d622ec6