Qt - ActiveX - How to handle custom out-parameter?

275 Views Asked by At

Considering an idl defined like bellow:

interface IServerConnection : IDispatch {
    [id(1), helpstring("method IsConnected")] HRESULT IsConnected([out] BOOL* pVal);
};

interface IClientControl : IDispatch {
    [id(1), helpstring("method GetServerConnection")] HRESULT GetServerConnection([out] IServerConnection** ppServerConnection);
};

The dumpcpp generate code like bellow:

class IServerConnection : public QAxObject
{
public:
    ...
    inline void IsConnected(int& pVal);
    ...
};


class ClientControl : public QAxWidget
{
public:
    ...

    ClientControl (IClientControl *iface)
    : QAxWidget()
    {
        initializeFrom(iface);
        delete iface;
    }

    inline void GetServerConnection(IServerConnection** ppServerConnection);
    ...
};

It returns type mismatch if I direct call ClientControl::GetServerConnection.

QAxBase: Error calling IDispatch member GetServerConnection: Type mismatch in parameter 0

How to get IServerConnection from the ClientControl?


With suggestion by @Remy Lebeau the idl changed to:

interface IServerConnection : IDispatch {
    [id(1), helpstring("method IsConnected")] HRESULT IsConnected([out] BOOL* pVal);
};

interface IClientControl : IDispatch {
    [id(1), helpstring("method GetServerConnection")] HRESULT GetServerConnection([out, retval] IServerConnection** ppServerConnection);
};

Then the source generated by dumpcpp:

class ClientControl : public QAxWidget
{
public:
    ...
    inline IServerConnection* GetServerConnection();
    ...
};

By calling GetServerConnection like:

ClientControl ctrl;
auto conn = ctrl.GetServerConnection();

It outputs:

QVariantToVARIANT: out-parameter not supported for "subtype".
QAxBase: Error calling IDispatch member GetServerConnection: Member not found

Changing the source code or implementation behind the idl is impossible. I can't change the interface to a return type, and that's another question.

It's more like a Qt problem rather than idl.

1

There are 1 best solutions below

0
Xiaofeng On

By using option --compat

Options
  ...
  --compat        Treat all coclass parameters as IDispatch.

dumpcpp generate source like bellow:

class ClientControl : public QAxWidget
{
public:
    ...
    inline void GetServerConnection(IDispatch** ppServerConnection);
    ...
};

The type of IDispatch can be handled by Qt.

Qt use QVariant to store and transfer arguments to VARIANT underneath, it handles IUnknown and IDispatch specially. Q_DECLARE_METATYPE is useless here, as the argument that the interface required is indeed a type(e.g. IServerConnection) derived from IDispatch, not the generated version, which is derived from QAxObject.