创建一个QT的dll工程,生成lib、dll文件后,新建一个测试工程,将动态库的头文件、lib文件加入到该工程里,通过头文件引用dll的导出类.
编译测试工程时报错:
1>GeneratedFiles\Release\moc_TestDll.cpp(58): warning C4273: “TestDll::qt_static_metacall”: dll 链接不一致
1> d:\code\test\vs\qtguiapplication1\qtguiapplication1\generatedfiles\release\../../TestDll.h(26): note: 参见“qt_static_metacall”的前一个定义 (编译源文件 GeneratedFiles\Release\moc_TestDll.cpp)
1>GeneratedFiles\Release\moc_TestDll.cpp(65): warning C4273: “staticMetaObject”: dll 链接不一致
1> d:\code\test\vs\qtguiapplication1\qtguiapplication1\generatedfiles\release\../../TestDll.h(26): note: 参见“public: static QMetaObject const TestDll::staticMetaObject”的前一个定义 (编译源文件 GeneratedFiles\Release\moc_TestDll.cpp)
1>GeneratedFiles\Release\moc_TestDll.cpp(65): **error C2491**: “TestDll::staticMetaObject”: 不允许 dllimport 静态数据成员 的定义
导出类头文件的代码如下:
#pragma once
#include
#ifndef BUILD_STATIC
# if defined(TESTDLL_LIB)
# define TESTDLL_EXPORT Q_DECL_EXPORT
# else
# define TESTDLL_EXPORT Q_DECL_IMPORT
# endif
#else
# define TESTDLL_EXPORT
#endif
class TESTDLL_EXPORT TestDll :
public QObject
{
Q_OBJECT
public:
TestDll();
~TestDll();
...
int f(int param);
};
查看出错的代码行是:Q_OBJECT
而Q_OBJECT是一个宏定义:
#define Q_OBJECT \
public: \
QT_WARNING_PUSH \
Q_OBJECT_NO_OVERRIDE_WARNING \
static const QMetaObject staticMetaObject; \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
QT_TR_FUNCTIONS \
private: \
Q_OBJECT_NO_ATTRIBUTES_WARNING \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
QT_WARNING_POP \
struct QPrivateSignal {}; \
QT_ANNOTATE_CLASS(qt_qobject, "")
其中QT_TR_FUNCTIONS又是一个宏定义:
# define QT_TR_FUNCTIONS \
static inline QString tr(const char *s, const char *c = Q_NULLPTR, int n = -1) \
{ return staticMetaObject.tr(s, c, n); } \
QT_DEPRECATED static inline QString trUtf8(const char *s, const char *c = Q_NULLPTR, int n = -1) \
{ return staticMetaObject.tr(s, c, n); }
由此可见,之所以编译会报错是因为导出类的类体里的Q_OBJECT定义了静态的内联函数,而这是被VS禁止的:
'identifier' : definition of dllimport function not allowed
Data, static data members, and functions can be declared as dllimports but not defined as dllimports.
错误描述:不允许定义dllimport修饰的函数
数据,静态数据成员和函数在声明时可以使用dllimport修饰,但定义时禁止使用dllimport修饰。
去掉类TestDll之前的TESTDLL_EXPORT,编译就通过了。
附微软官方文档说明:
https://docs.microsoft.com/zh-cn/cpp/error-messages/compiler-errors-1/compiler-error-c2491?view=vs-2019
Compiler Error C2491
2016/11/04
'identifier' : definition of dllimport function not allowed
Data, static data members, and functions can be declared as dllimports but not defined as dllimports.
To fix this issue, remove the __declspec(dllimport) specifier from the definition of the function.
The following sample generates C2491:
// C2491.cpp
// compile with: /c
// function definition
void __declspec(dllimport) funcB() {} // C2491
// function declaration
void __declspec(dllimport) funcB(); // OK