无法从完全有效的 dll 符号导出,否则
Can't export from dll symbols that are perfectly valid otherwise
我在Linux下实现了一个应用:
- 主要使用 Qt 作为库;
- 由几个库和一个主图形用户界面应用程序组成。
当我使我的代码符合 Visual Studio 2015 年的编译器时,我偶然发现了以下 dllexport 问题(它实际上是一个截断的代码):
#include <QVariant>
#include <QList>
class SNIPPEDSHARED_EXPORT Snipped : public QList<QVariant>
{
public:
Snipped();
};
SNIPPEDSHARED_EXPORT 是 classical:
#if defined(SNIPPED_LIBRARY)
# define SNIPPEDSHARED_EXPORT __declspec(dllexport)
#else
# define SNIPPEDSHARED_EXPORT __declspec(dllimport)
#endif
代码生成:
C:\Qt.7\msvc2015_64\include\QtCore\qhashfunctions.h:110: erreur : C2665: 'qHash': none of the 22 overloads could convert all the argument types
C:\Qt.7\msvc2015_64\include\QtCore\qhashfunctions.h:110: erreur : C2056: illegal expression
错误信息足够明确,我什至发现有人定义了自己的 qHash:
- http://www.qtforum.org/article/19733/qmultihash-qvariant-compiler-error-c2665.html
- qvariant as key in qhash
困扰我的事情:
- 我直接使用 QList 而不是 qHash;我很清楚 QList 可能在内部使用 qHash 但代码使用 gcc 运行顺利:所以 Qt 似乎提供了所需的东西;
- 当我在常规二进制文件(不是库文件)中构建确切的 class 时,所有运行都完美(windows 或 linux)。
- 当我删除
__declspec
时,库正在完美构建
我花时间阅读了有关导出模板的文档,因为这似乎是真正的问题(我什至花时间阅读了 Qt 源代码(嘿,他们的代码是 运行 :-))):
- 使用显式模板实例化:here and here
- 挖掘一些历史数据:How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object
但所描述的问题似乎并不适用。我尝试了所有类型的组合,但 none 成功了(这本来就是侥幸)。
代码如此简短,我想我错过了一些基本的东西(抱歉:这不是一个真正有趣的问题,而且令人费解)。
有人有想法吗?
P.S.: 完整技术数据:
- Visual Studio 2015 社区版,最后更新:14.0.25424.00 更新 3
- Visual C++ 2015 00322-20000-00000-AA285
- 使用 Windows 套件 10:10.0.10586.0
- 通过 QtCreator 创建库项目
snipped.pro
QT -= gui
TARGET = snipped
TEMPLATE = lib
DEFINES += SNIPPED_LIBRARY
SOURCES += snipped.cpp
snipped.cpp
#include "snipped.h"
#include <QDebug>
Snipped::Snipped()
{
qDebug("Coucou !");/*some code is required otherwise the build will generate nothing*/
}
snipped.h
#ifndef SNIPPED_H
#define SNIPPED_H
#include "snipped_global.h"
#include <QVariant>
#include <QList>
class SNIPPEDSHARED_EXPORT Snipped : public QList<QVariant>
{
public:
Snipped();
};
#endif // SNIPPED_H
snipped_global.h
#ifndef SNIPPED_GLOBAL_H
#define SNIPPED_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(SNIPPED_LIBRARY)
# define SNIPPEDSHARED_EXPORT __declspec(dllexport)
#else
# define SNIPPEDSHARED_EXPORT __declspec(dllimport)
#endif
#endif // SNIPPED_GLOBAL_H
我在 « Microsoft Specific » 上找到了这个问题的原因:
我引用:
When you declare a class dllexport, all its member functions and
static data members are exported. You must provide the definitions of
all such members in the same program. Otherwise, a linker error is
generated.
为了完整:
The one exception to this rule applies to pure virtual functions, for
which you need not provide explicit definitions. However, because a
destructor for an abstract class is always called by the destructor
for the base class, pure virtual destructors must always provide a
definition. Note that these rules are the same for nonexportable
classes.
If you export data of class type or functions that return classes, be
sure to export the class.
它将教会我不要浏览文档。
我在Linux下实现了一个应用:
- 主要使用 Qt 作为库;
- 由几个库和一个主图形用户界面应用程序组成。
当我使我的代码符合 Visual Studio 2015 年的编译器时,我偶然发现了以下 dllexport 问题(它实际上是一个截断的代码):
#include <QVariant>
#include <QList>
class SNIPPEDSHARED_EXPORT Snipped : public QList<QVariant>
{
public:
Snipped();
};
SNIPPEDSHARED_EXPORT 是 classical:
#if defined(SNIPPED_LIBRARY)
# define SNIPPEDSHARED_EXPORT __declspec(dllexport)
#else
# define SNIPPEDSHARED_EXPORT __declspec(dllimport)
#endif
代码生成:
C:\Qt.7\msvc2015_64\include\QtCore\qhashfunctions.h:110: erreur : C2665: 'qHash': none of the 22 overloads could convert all the argument types
C:\Qt.7\msvc2015_64\include\QtCore\qhashfunctions.h:110: erreur : C2056: illegal expression
错误信息足够明确,我什至发现有人定义了自己的 qHash:
- http://www.qtforum.org/article/19733/qmultihash-qvariant-compiler-error-c2665.html
- qvariant as key in qhash
困扰我的事情:
- 我直接使用 QList 而不是 qHash;我很清楚 QList 可能在内部使用 qHash 但代码使用 gcc 运行顺利:所以 Qt 似乎提供了所需的东西;
- 当我在常规二进制文件(不是库文件)中构建确切的 class 时,所有运行都完美(windows 或 linux)。
- 当我删除
__declspec
时,库正在完美构建
我花时间阅读了有关导出模板的文档,因为这似乎是真正的问题(我什至花时间阅读了 Qt 源代码(嘿,他们的代码是 运行 :-))):
- 使用显式模板实例化:here and here
- 挖掘一些历史数据:How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object
但所描述的问题似乎并不适用。我尝试了所有类型的组合,但 none 成功了(这本来就是侥幸)。
代码如此简短,我想我错过了一些基本的东西(抱歉:这不是一个真正有趣的问题,而且令人费解)。
有人有想法吗?
P.S.: 完整技术数据:
- Visual Studio 2015 社区版,最后更新:14.0.25424.00 更新 3
- Visual C++ 2015 00322-20000-00000-AA285
- 使用 Windows 套件 10:10.0.10586.0
- 通过 QtCreator 创建库项目
snipped.pro
QT -= gui TARGET = snipped TEMPLATE = lib DEFINES += SNIPPED_LIBRARY SOURCES += snipped.cpp
snipped.cpp
#include "snipped.h" #include <QDebug> Snipped::Snipped() { qDebug("Coucou !");/*some code is required otherwise the build will generate nothing*/ }
snipped.h
#ifndef SNIPPED_H #define SNIPPED_H #include "snipped_global.h" #include <QVariant> #include <QList> class SNIPPEDSHARED_EXPORT Snipped : public QList<QVariant> { public: Snipped(); }; #endif // SNIPPED_H
snipped_global.h
#ifndef SNIPPED_GLOBAL_H #define SNIPPED_GLOBAL_H #include <QtCore/qglobal.h> #if defined(SNIPPED_LIBRARY) # define SNIPPEDSHARED_EXPORT __declspec(dllexport) #else # define SNIPPEDSHARED_EXPORT __declspec(dllimport) #endif #endif // SNIPPED_GLOBAL_H
我在 « Microsoft Specific » 上找到了这个问题的原因: 我引用:
When you declare a class dllexport, all its member functions and static data members are exported. You must provide the definitions of all such members in the same program. Otherwise, a linker error is generated.
为了完整:
The one exception to this rule applies to pure virtual functions, for which you need not provide explicit definitions. However, because a destructor for an abstract class is always called by the destructor for the base class, pure virtual destructors must always provide a definition. Note that these rules are the same for nonexportable classes.
If you export data of class type or functions that return classes, be sure to export the class.
它将教会我不要浏览文档。