error LNK2001: unresolved external symbol “public: static struct QMetaObject 报错

最近在项目中碰到了这个报错,分析一下这个报错的产生原因以及解决办法。

首先这个错误是链接阶段的问题,也就是说链接器在通过符号查找对应的实现的时候没有找到对应的。

在网上有总结过一些可能的原因:

This can occur for four reasons:
1) the MOC compiler didn't run to create the *_moc.cpp file from the class header file,
2) MOC did run, but the generated cpp file wasn't compiled,
3) MOC did run, but the class definition was missing the Q_OBJECT macro (which defines the staticMetaObject embedded class) so the code inserted by the macro wasn't there, or
4) the object code compiled from the cpp file wasn't linked into the executable.

In the linux world, there is another possibility: the object files / libraries were not linked in the correct order. Object files must be presented to the gcc / g++ linker so any object file that is dependent on another object file (.o or .lib) must appear -before- that .o or .lib in the link command. Otherwise, dependencies discovered by the linker -after- the file that defines them has been processed will remain unresolved.

The MSVC linker is smarter; it apparently builds a table of all references contained in the object files and can resolve references anywhere they occur when processing the link command.

接下来简单介绍一个demo:

项目分为三个文件:

main.cpp
testCore.hpp
testCore.cpp

其中testCore类被封装成一个库,通过在Cmake里面添加如下代码:

#set library
set(TARGET_CORE "test-Core")
set(QUICKVTK_QT_MODULES Core Gui Widgets Quick Qml Concurrent Network DBus PrintSupport)
......
set(LINK_LIBRARIES PUBLIC ${VTK_LIBRARIES} PUBLIC Qt5::Core PUBLIC Qt5::Widgets PUBLIC Qt5::Gui PUBLIC Qt5::Quick PUBLIC Qt5::Qml PUBLIC Qt5::Concurrent)
......
add_library(${TARGET_CORE} SHARED Core/testcore.hpp Core/testcore.cpp)
set_target_properties(${TARGET_CORE} PROPERTIES PUBLIC_HEADER Core/testcore.hpp)
target_link_libraries(${TARGET_CORE} ${LINK_LIBRARIES})
......
target_link_libraries(${PROJECT_NAME}
  PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick ${TARGET_CORE})

在main.cpp中添加如下代码:

#include "Core/testcore.hpp"
......
    engine.rootContext()->findChild();
......

项目编译之后,产生如下报错:

main.obj:-1: error: LNK2001: 无法解析的外部符号 "public: static struct QMetaObject const testCore::staticMetaObject" (?staticMetaObject@testCore@@2UQMetaObject@@B) [D:\Projects\qtprojects\Test\build-testLinkQtLibrary-Desktop_Qt_5_15_2_MSVC2019_64bit\testLinkQtLibrary.vcxproj]

相同的代码,在ubuntu和mac平台下测试没问题,

后来想了一下原因,看了一下Qt官方文档Creating Shared Libraries | Qt 5.15

突然想起来,在windows平台库需要加上import或者export,不然的话会有问题。

于是增加一个testCore_global.hpp

里面增加如下内容:

#ifndef TESTCORE_GLOBAL_HPP
#define TESTCORE_GLOBAL_HPP

#include 

#if defined(TESTCORE_LIBRARY)
#  define TESTCORE_EXPORT Q_DECL_EXPORT
#else
#  define TESTCORE_EXPORT Q_DECL_IMPORT
#endif


#endif // TESTCORE_GLOBAL_HPP

注意这里有一个预定义的名称 “TESTCORE_LIBRARY”,这个需要在CMake文件里面启用,这里再CMake文件添加一行:

target_compile_definitions(${TARGET_CORE} PRIVATE TESTCORE_LIBRARY)

这一行的作用是,在编译阶段,为这个库增加这个变量。

也就是说,在编译库的时候,我们定义了这个TESTCORE_LIBRARY变量,这样在testCore_global.hpp中,对应的TESTCORE_EXPORT就是Q_DECL_EXPORT。

在编译主程序的时候,不会增加这个变量,所以主程序在引用testCore_global.hpp的时候,这个TESTCORE_EXPORT就是Q_DECL_IMPORT。

当然了,还有很重要的一步就是在testCore.hpp中,要修改类的声明:

class TESTCORE_EXPORT testCore
.......

这样再编译即可正常通过。

你可能感兴趣的:(QT,c++,弹出设备,cmake,qt,开发语言)