#1 2014-04-17 22:12:25

azubieta
Member
Registered: 2014-04-17
Posts: 4

Usign QtClases as interfaces.

I would like to use the clases defined in Qt as interfaces for my services, but when I declare then, the function template "qobject_cast" clash with the one defined inside the Qt Framework.
Is there any work around to fix this? I'm doing it right?

this is the code I had use:
#include <usServiceInterface.h>
#include <QObject>
#include <QWidget>

US_DECLARE_SERVICE_INTERFACE(QObject, "org.qt-project.Qt.QObject")
US_DECLARE_SERVICE_INTERFACE(QWidget, "org.qt-project.Qt.QWidget")

Offline

#2 2014-04-18 07:25:32

sascha
Administrator
Registered: 2012-05-04
Posts: 45

Re: Usign QtClases as interfaces.

In principal you are doing it right. However, the US_DECLARE_SERVICE_INTERFACE macro was not designed with this use case in mind (using it on QObject derived classes from external libraries). Essentially, the macro only specializes the us_service_interface_iid function template (and in the Qt case, also specializes qobject_cast, which is clashing with the existing definition for QObject). So instead of using the macro, you can just specialize the template yourself like:

template<> inline const char* us_service_interface_iid<QObject>()
{ return "org.qt-project.Qt.QObject"; }

Having said that, you might want to consider introducing your own "marker interface" instead, depending on what you actually want to do. For example

struct IDesktopWidget {};

US_DECLARE_SERVICE_INTERFACE(IDesktopWidget, "org.my-project.IDesktopWidget")

void implement_and_register()
{
  class MyDesktopWidget : public QWidget, public IDesktopWidget
  {
    // implementation goes here...
  };
  IDesktopWidget* desktopWidget = new MyDesktopWidget;
  us::GetModuleContext()->RegisterService(desktopWidget);
}

void use_widget()
{
  us::ModuleContext* context = us::GetModuleContext();
  us::ServiceReference<IDesktopWidget> ref = context->GetServiceReference<IDesktopWidget>();
  if (ref)
  {
    QWidget* desktopWidget = qobject_cast<QWidget*>(context->GetService(ref));
    // do something...
  }
}

Offline

#3 2014-04-18 23:24:12

azubieta
Member
Registered: 2014-04-17
Posts: 4

Re: Usign QtClases as interfaces.

I had tried the "marker interface", but it fails saying that can't cast a *IDesktopWidget to a *QObject. I tried using "dynamic_cast" but I had to add at least a virtual function to my interface. Resulting in something like this:

struct IDesktopWidget {
    virtual ~IDesktopWidget();
};

US_DECLARE_SERVICE_INTERFACE(IDesktopWidget, "org.my-project.IDesktopWidget")

void implement_and_register()
{
  class MyDesktopWidget : public QWidget, public IDesktopWidget
  {
    // implementation goes here...
  };
  IDesktopWidget* desktopWidget = new MyDesktopWidget;
  us::GetModuleContext()->RegisterService(desktopWidget);
}

void use_widget()
{
  us::ModuleContext* context = us::GetModuleContext();
  us::ServiceReference<IDesktopWidget> ref = context->GetServiceReference<IDesktopWidget>();
  if (ref)
  {
    QWidget* desktopWidget = dynamic_cast<QWidget*>(context->GetService(ref));
    // do something...
  }
}

Offline

#4 2014-04-19 23:04:19

sascha
Administrator
Registered: 2012-05-04
Posts: 45

Re: Usign QtClases as interfaces.

I am surprised that your initial approach with a marker interface did not work. Generally it should and there might have been just a small issue with your or the CppMicroServices code.

Also, my above example wasn't complete when using qobject_cast. Remember to use Q_INTERFACES in the implementing class and running moc on it (this is needed for the qobject_cast call):

struct IDesktopWidget {
};

US_DECLARE_SERVICE_INTERFACE(IDesktopWidget, "org.my-project.IDesktopWidget")

class MyDesktopWidget : public QWidget, public IDesktopWidget
{
  Q_OBJECT
  Q_INTERFACES(IDesktopWidget)

  // implementation goes here...
};

The US_DECLARE_SERVICE_INTERFACE acts as a replacement for the Q_DECLARE_INTERFACE macro and adds a CppMicroServices specific template specialization. With this approach, you don't need a virtual method in the interface (qobject_cast doesn't use RTTI).

Let me know if it doesn't work out.

Offline

#5 2014-04-21 16:09:15

azubieta
Member
Registered: 2014-04-17
Posts: 4

Re: Usign QtClases as interfaces.

It seems that it's something missing related to the QT MOC. After using the "Q_INTERFACES" macro in my class it complains that the "Interface isn't declared".
But when I use both interface declarations together they clash.

struct IPanel {
};
Q_DECLARE_INTERFACE(IPanel, "org.moonlightde.panel.IPanel/1.0")
US_DECLARE_SERVICE_INTERFACE(IPanel, "org.moonlightde.panel.IPanel/1.0")

Now the funny part is that if I remove the QT interface declaration without clean the build directory and try to build again it works well. Any thoughts ?

struct IPanel {
};
//Q_DECLARE_INTERFACE(IPanel, "org.moonlightde.panel.IPanel/1.0")
US_DECLARE_SERVICE_INTERFACE(IPanel, "org.moonlightde.panel.IPanel/1.0")

By the way I'm using Qt5.2, with cmake in Linux.

Last edited by azubieta (2014-04-21 16:11:20)

Offline

#6 2014-06-02 00:43:16

sascha
Administrator
Registered: 2012-05-04
Posts: 45

Re: Usign QtClases as interfaces.

Offline

#7 2014-07-02 21:28:44

azubieta
Member
Registered: 2014-04-17
Posts: 4

Re: Usign QtClases as interfaces.

It worked like a sharm! Now I'm creating interfaces with qt slots and signals.

Thanks!

Offline

Board footer

Powered by FluxBB