【问题标题】:Qt signals missing in external dll外部 dll 中缺少 Qt 信号
【发布时间】:2014-02-13 05:31:34
【问题描述】:

我在我的应用程序中使用的 iris xmpp 库中有信号。在 Mac OS X 和 Linux 上一切正常,但 Windows 会产生一大堆未找到信号的警告。

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

我尝试使用的一个信号示例是

signals:
    void srvLookup(const QString &server);

我的连接调用

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);

这是我的实际插槽之一

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

我不明白为什么 mac 和 linux 可以工作,而 windows 不能。我已经考虑过编译器选项,但我使用 cmake,所以除非我的 linux gcc 和我的 mingw gcc 之间存在巨大差异,否则我不明白这有什么关系。我正在使用 C++11 功能,这在我的连接调用中很明显。但是我适当地编译和链接,所以我假设 C++11 的功能像我预期的那样工作。有人有想法吗?

编辑:

我正在使用 Qt5.2.0 MinGW OpenGL。我正在使用Qt5.2.0附带的MinGW,即MinGW48 32。我正在编译库iris,与我的应用程序同时使用cmake to automoc,将其设置为链接依赖项,并包含正确的标题。

EDIT2:包括了我所有的连接调用。

【问题讨论】:

  • 你在 Windows 上使用的 Qt 和 GCC 匹配吗? XMMP 库是否也与您使用的 GCC 匹配?
  • 编辑了有关我如何构建的信息。
  • 采用函数指针的连接不需要 C++11。警告提到您的连接语句中未列出的类,因此必须有其他连接失败。也许来自 XMPP 本身?
  • @Frank Osterfeld 这只是我的连接语句之一,它们看起来都一样。我想我会和他们一起编辑更多。

标签: c++ windows qt c++11 mingw


【解决方案1】:

事实证明,我缺乏 Windows 开发结果让我感到很痛苦。所以对于windows,如果你在windows上导出符号,你需要包含这个奇怪的语句“__declspec(dllexport)”。

所以我所做的是我添加了

/**
 * @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

然后我会在每个人身上使用它

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

这解决了我的问题。

有关这方面的更多信息,请访问 hereherehere

【讨论】:

  • 我可以补充一点,如果您使用的是 CMake,set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 似乎不起作用 - 您需要将 XYZ_EXPORT 添加到您的 Q_OBJECT 类中。
猜你喜欢
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多