PDA

View Full Version : COM object and QtVariant casting issue



mlago
3rd January 2017, 08:16
Hello every one,
I'm trying to use a Windows COM object and I'm having trouble casting a returned function value. I am using Qt 5.7.0 and I got .h and .cpp file for COM object with dumpcpp tool. For simplicity I show only the kind of interest:


class SCAPILIB_EXPORT IAttrList : public QAxObject
{
public:
IAttrList(IDispatch *subobject = 0, QAxObject *parent = 0)
: QAxObject((IUnknown*)subobject, parent)
{
internalRelease();
}

/*
Method AddItem

method AddItem

*/
inline void AddItem(Attr Attribute, const QVariant& value);

/*
Method FindItemIndex

method FindItemIndex

*/
inline int FindItemIndex(int startIndex, SCAPILib::Attr Attribute);

/*
Method GetCount

method GetCount

*/
inline int GetCount();

/*
Method GetIndex

method GetIndex

*/
inline QVariant GetIndex(int index, Attr& pAttribute);

/*
Method GetItem

method GetItem

*/
inline QVariant GetItem(Attr Attribute);

/*
Method OutputToString

method OutputToString

*/
inline QString OutputToString();

/*
Method RestoreFromBlob

method RestoreFromBlob

*/
inline void RestoreFromBlob(QVariant blob);

/*
Method SaveToBlob

method SaveToBlob

*/
inline void SaveToBlob(QVariant& pBlob);

/*
Method SetIndex

method SetIndex

*/
inline void SetIndex(int index, SCAPILib::Attr Attribute, const QVariant& value);

// meta object functions
static const QMetaObject staticMetaObject;
virtual const QMetaObject *metaObject() const { return &staticMetaObject; }
virtual void *qt_metacast(const char *);
};

template<>
struct QMetaTypeFunctionHelper<SCAPILib::IAttrList, /* Accepted */ true> {
static void Destruct(void *t)
{
Q_UNUSED(t)
static_cast<SCAPILib::IAttrList*>(t)->SCAPILib::IAttrList::~IAttrList();
}
static void *Construct(void *where, const void *t)
{
Q_ASSERT(!t);
Q_UNUSED(t)
return new (where) SCAPILib::IAttrList;
}
#ifndef QT_NO_DATASTREAM
static void Save(QDataStream &stream, const void *t) { stream << *static_cast<const SCAPILib::IAttrList*>(t); }
static void Load(QDataStream &stream, void *t) { stream >> *static_cast<SCAPILib::IAttrList*>(t); }
#endif // QT_NO_DATASTREAM
};
The function GetItem always returned a QVariant, usually the QVariant contain a QString, QInt or QBool, but with a determinate attribute the returned value will be a pointer to the base class(IAttrList *).


inline QVariant IAttrList::GetItem(Attr Attribute)
{
QVariant qax_result;
void *_a[] = {(void*)&qax_result, (void*)&Attribute};
qt_metacall(QMetaObject::InvokeMetaMethod, 12, _a);
return qax_result;
}

I can use the function of the COM object just fine, except when it will be return a indicated class pointer. In this case de QVariant returnet type is (IUnknown *) and I not able to cast this to (IAttrLits *).

I'm tried with:


IAttrList * Attr = AttrList.GetItem(Some_Attribute).Value<IAttrList *>();
But compiler returned error: static assertion failed: qobject_cast requires the type to have a Q_OBJECT macro

Which I understand is normal because, according to QT documentation, classes derived from QAxObject can not contain the Q_OBJECT macro.

I have also tried with:


IAttrList * attr = static_cast<IAttrList *>(AttrList.GetItem(Some_attribute).data());
and

IAttrList * attr = static_cast<IAttrList *>(AttrList.GetItem(Some_attribute).value<void *>();
It's compile but the AttrList pointer does not seem to be valid because I get a segmentation fault to try use it.

I have also read about the QueryInterface method and I have tried with something like:


QVariant * var =AttrList.GetItem(some_attribute);
HRESULT hr = AttrList.queryInterface(UuID,(void **)&var);
The problen is that this interface not have a UUID and I can't do the call.

Also I have read about get a class instance with QuerySubOject but a QVariant Objects does not have it.

I do not know how to solve it, any subgestion?. Thanks in advanced.

d_stranz
3rd January 2017, 22:16
Try using "__uuidof( IAttrList )" where you wrote "UuID" in your queryInterface() call.

mlago
4th January 2017, 08:32
Hi, thankyou for answer.

I've tried how you say with error: error: '__mingw_uuidof' was not declared in this scope

QVariant var = JswAttrList.GetItem(Some_attribute);
HRESULT hr = AttrList.queryInterface(__uuidof(JSWSCAPILib::IJsw AttrList),(void **)&var);
__uuidof is a MVC++ extensión. I have to say that I am using mingw as compiler. Them I've tried to get UUID Class from Visual C++ with this simple test:

String^ s = __uuidof(JSWSCAPILib::IJswAttrList);
with this compiler error: error C2787: 'SCAPILib::IAttrList' : No GUIDs have been associated with this object

anda_skoa
4th January 2017, 15:13
I think (void**)&var does not make sense, that is retinterpreting a pointer to a QVariant, no?

You write that the QVariant type is IUnknown*, does this compile?


IUnknown *obj = var.value<IUnknown*>();


Cheers,
_

mlago
4th January 2017, 16:26
Thankyou for reply.

I think (void**)&var does not make sense, that is retinterpreting a pointer to a QVariant, no?
In a sense yes.

You write that the QVariant type is IUnknown*, does this compile?


IUnknown *obj = var.value<IUnknown*>();


Cheers,
_
Yes, compile Ok. What do you suggest?.

anda_skoa
4th January 2017, 18:20
Yes, compile Ok. What do you suggest?.

I haven't worked with COM or ActiveQt, but if the object is stored as a IUnknown in the QVariant, then just extract it as such and then use whatever API is provided for working with COM interfaces on that pointer.

I.e. the QVariant is just a transport wrapper, like an envelope. You take the transported item out of the envelope and forget about the envelope.

Cheers,
_

mlago
4th January 2017, 19:30
It sounds really easy :rolleyes:

Seriously, I was thinking about something like that but still not know very well as how. What amazes me is that I can not do it any other way.

I appreciate your effort.

d_stranz
5th January 2017, 05:12
I've tried how you say with error: error: '__mingw_uuidof' was not declared in this scope

So that sounds like mingw knows about it, but you haven't included the header file where it is defined. I don't use mingw, so I can't really tell you where to look. What does Google tell you if you paste "__mingw_uuidof" into the search box?

mlago
5th January 2017, 09:06
Hi,
__uuidof is defined in _mingw.h

#define __uuidof(type) __mingw_uuidof<__typeof(type)>()
The _mingw.h file begins by saying:

/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
and my compiler versión is 32 bits :(

The most usable that I found in google is this thread https://forum.qt.io/topic/35324/solved-com-interface-to-canoe/15, but it is not applicable to me in the same way that it is exposed there. I've already tried compiling it with ole32.lib and nothing has changed.

As I said I have also tried to capture the value returned by __uuidof in MS visual C ++ with the idea of using that UUID in my application in Qt. From this test what I consider relevant is the returned message by compiler error C2787: 'SCAPILib::IAttrList' : No GUIDs have been associated with this object. Which suggests to me that this class has no definite UUID. Then I have tried to define an IID_IATTRLIST variable in the IAttrList class without getting QueryInterface to return anything other than a null pointer. I think this is a dead end