Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt signals missing in external dll

I have signals in a library, iris xmpp library, that I use in my application. Everything works fine on Mac OS X and Linux, but Windows produces a whole bunch of signals not found warnings.

warning: QObject::connect: signal not found in XMPP::AdvancedConnector
warning: QObject::connect: signal not found in XMPP::AdvancedConnector
warning: QObject::connect: signal not found in XMPP::AdvancedConnector
warning: QObject::connect: signal not found in XMPP::AdvancedConnector
warning: QObject::connect: signal not found in XMPP::QCATLSHandler
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::ClientStream
warning: QObject::connect: signal not found in XMPP::Client
warning: QObject::connect: signal not found in XMPP::Client
warning: QObject::connect: signal not found in XMPP::Client
warning: QObject::connect: signal not found in XMPP::Client

An example of one signal that I am trying to use is

signals:
    void srvLookup(const QString &server);

my connect calls

conn = std::make_shared<XMPP::AdvancedConnector>();
QObject::connect(conn.get(), &XMPP::AdvancedConnector::srvLookup, this, &XmppConnection::connServerLookupHandler);
QObject::connect(conn.get(), &XMPP::AdvancedConnector::srvResult, this, &XmppConnection::connServerResultHandler);
QObject::connect(conn.get(), &XMPP::AdvancedConnector::httpSyncStarted, this, &XmppConnection::connHttpSyncStartedHandler);
QObject::connect(conn.get(), &XMPP::AdvancedConnector::httpSyncFinished, this, &XmppConnection::connHttpSyncFinishedHandler);

if(QCA::isSupported("tls")) {
    tls = make_unique<QCA::TLS>();
    tlsHandler = make_unique<XMPP::QCATLSHandler>(tls.get());
    // dont check the certificate because we self sign
    tlsHandler->setXMPPCertCheck(false);
    QObject::connect(tlsHandler.get(), &XMPP::QCATLSHandler::tlsHandshaken, this, &XmppConnection::tlsHandshakenHandler);
} else {
    tls = 0;
    tlsHandler = 0;
}

stream = std::make_shared<XMPP::ClientStream>(conn.get(), tlsHandler.get());
QObject::connect(stream.get(), &XMPP::ClientStream::connected, this, &XmppConnection::streamConnectedHandler);
QObject::connect(stream.get(), &XMPP::ClientStream::securityLayerActivated, this, &XmppConnection::streamSecurityLayerActivatedHanlder);
QObject::connect(stream.get(), &XMPP::ClientStream::needAuthParams, this, &XmppConnection::streamNeedAuthParamsHandler);
QObject::connect(stream.get(), &XMPP::ClientStream::authenticated, this, &XmppConnection::streamAuthenticatedHandler);
QObject::connect(stream.get(), &XMPP::ClientStream::connectionClosed, this, &XmppConnection::streamConnectionClosedHandler);
QObject::connect(stream.get(), &XMPP::ClientStream::delayedCloseFinished, this, &XmppConnection::streamDelayedCloseFinished);
QObject::connect(stream.get(), &XMPP::ClientStream::readyRead, this, &XmppConnection::streamReadyRead);
QObject::connect(stream.get(), &XMPP::ClientStream::stanzaWritten, this, &XmppConnection::streamStanzaWritten);
QObject::connect(stream.get(), &XMPP::ClientStream::warning, this, &XmppConnection::streamWarningHandler);
QObject::connect(stream.get(), &XMPP::ClientStream::error, this, &XmppConnection::streamErrorHandler);

xmpp = std::make_shared<XMPP::Client>();
QObject::connect(xmpp.get(), &XMPP::Client::rosterRequestFinished, this, &XmppConnection::onRosterRequestFinished);
QObject::connect(xmpp.get(), &XMPP::Client::rosterItemAdded, this, &XmppConnection::onRosterItemAdded);
QObject::connect(xmpp.get(), &XMPP::Client::rosterItemUpdated, this, &XmppConnection::onRosterItemUpdated);
QObject::connect(xmpp.get(), &XMPP::Client::rosterItemRemoved, this, &XmppConnection::onRosterItemRemoved);

Here is one of my actual slots

void XmppConnection::connServerLookupHandler(const QString &server)
{
    qDebug() << "Looking up Server: " << server;
    return;
}

I cannot figure out why mac and linux work and windows doesn't. I have thought about compiler options, but I use cmake so unless there is some huge difference between my linux gcc and my mingw gcc I dont see why that would matter. I am using C++11 features as evident by my connect call. But I appropriately compile and link so I am assuming the C++11 features are working like I expected. Anyone have an idea?

EDIT:

I am using Qt5.2.0 MinGW OpenGL. I am using the MinGW that comes with Qt5.2.0, i.e. MinGW48 32. I am compiling the library, iris, at the same time as my application and am using cmake to automoc, to set it as a link dependency, and include the right headers.

EDIT2: Included all of my connect calls.

like image 994
David Stocking Avatar asked Jan 22 '14 22:01

David Stocking


1 Answers

Turns out my lack of windows development turned out to bite me in the butt. So for windows, you need to include this strange statment "__declspec(dllexport)" if you are exporting symbols on windows.

So what I did is I added

/**
 * @brief Allows for windows exported symbols
 *
 * Windows requries a special modifier to allow them to export correctly.
 * This macro allows that while leaving Mac OS X and Linux alone.
 *
 * While Qt can tell us if it was make for WIN32, MAC, or LINUX, It cannot
 * tell us if we are being statically or dynamically linked. That is why
 * this is using the CMake variables instead of Qt
 */
#if defined (_WIN32)
  // cmake makes this variable if your a shared library (projectname_EXPORTS)
  #if defined(iris_EXPORTS)
    #define IRIS_EXPORT Q_DECL_EXPORT
  #else
    #define IRIS_EXPORT Q_DECL_IMPORT
  #endif /* iris_EXPORTS */
#else /* defined (_WIN32) */
 #define IRIS_EXPORT
#endif

Then I would use this on every

class IRIS_EXPORT ClassNameHere { ... }
IRIS_EXPORT void StaticFunctionNameHere(){...}

And this fixed my problems.

For more info on this go to here, here, or here.

like image 127
David Stocking Avatar answered Nov 15 '22 03:11

David Stocking