Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
4.6.2
-
None
-
Qt 4.6.2 (commercial installer) , Windows XP, Python 2.4,
Python for Windows extensions build 214 (pywin32-214.win32-py2.4),
Visual Studio 2005
Description
This problem affects ActiveQt when it is used as a COM server and called from Python using the python win32 extensions.
(http://python.net/crew/mhammond/win32/)
This may not strictly be a Qt bug since the python extensions could be doing something non-standard but I think ActiveQt should be able to handle this better.
The example code is based on the example comapp. If we define 2 classes MyObject and Application as below
class MyObject : public QObject { Q_OBJECT Q_CLASSINFO("ClassID", "{3A29C72F-951E-4de8-97BA-013B08548E4C}") Q_CLASSINFO("InterfaceID", "{6E737237-4AB6-40ee-8141-AB62927282D8}") Q_CLASSINFO("RegisterObject", "yes") public: MyObject(QObject *parent = 0); public slots: QString Name() const {return "something";} }; class Application : public QObject { Q_OBJECT Q_CLASSINFO("ClassID", "{51AD6550-96F0-4eb6-96C6-B0A08093ACAA}") Q_CLASSINFO("InterfaceID", "{A110585A-E6C9-4375-86EB-BE903BEDDB14}") Q_CLASSINFO("RegisterObject", "yes") public: Application(QObject *parent = 0); public slots: MyObject* CreateObject(); QString Function(MyObject* ob); };
When we call these functions from Python COM, creating the objects and accessing simple functions works, that is, from python we can do:
import win32com.client
a = win32com.client.Dispatch("ComTest.Application")
o = a.GetObject()
print o.Name()
This will work. But if we try:
a.Function(o)
Then it does not.
The reason is that the Python COM extensions are passing an IUnknown* for the object, but ActiveQt is expecting an IDispatch.
In qaxtypes.cpp, VARIANTToQVariant the IUnknown type is converted as a raw pointer value. This means that the called slot
QString Function(MyObject* ob);
gets a QAXServerBase object which has been cast to a MyObject* - that is the wrapper is passed to the function instead of the wrapee and so the data is garbage.
This happens with no error messages from ActiveQt about incompatible data types
I can work around this with the following change to qaxtypes.cpp. If the case statement for handling IUnknowns is replaced by
case VT_UNKNOWN: case VT_UNKNOWN|VT_BYREF: { IUnknown *unkn = 0; if (arg.vt & VT_BYREF) unkn = *arg.ppunkVal; else unkn = arg.punkVal; #ifdef QAX_SERVER IAxServerBase *iface = 0; if (unkn && typeName != "IUnknown*") unkn->QueryInterface(IID_IAxServerBase, (void**)&iface); if (iface) { QObject *qObj = iface->qObject(); iface->Release(); var = QVariant(qRegisterMetaType<QObject*>(qObj ? QByteArray(qObj->metaObject()->className()) + '*' : typeName), &qObj); } else #endif qVariantSetValue(var, unkn); } break;
Then the COM calls from Python work correctly. This just copies some of the code from the IDispatch handler into the IUnknown handler.
I tested this with 4.6.2 but there do not seem to have been any significant updates to Active Qt for 4.7 so I am guessing the problem still exists there.
Attachments
Issue Links
- relates to
-
QTBUG-49712 Unable to write to property from python (ActiveQt)
- Closed
Gerrit Reviews
For Gerrit Dashboard: QTBUG-12202 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
144585,3 | WIP: Extract QAXServerBase from IUnknown for scripting. | 5.6 | qt/qtactiveqt | Status: DEFERRED | -2 | 0 |