Unresolved symbol in user DLL "public: static struct QMetaObject"
-
I search Qt's community and stackoverflow, found there are many related posts, but these are not same problem what I am.
I write a user-defined widget inheite from
QOpenGLWidget
, and create a DLL for it usingCMake
: qt-open-glpoint-cloud.The whole error message is:
error LNK2001: 无法解析的外部符号 "public: static struct QMetaObject const test::gl_painter::GLCloudWidget2D::staticMetaObject" (?staticMetaObject@GLCloudWidget2D@gl_painter@test@@2UQMetaObject@@B)
The CMake script list bellow:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) file(GLOB SRCS src/*.cc) file(GLOB HEADERS ${PROJECT_SOURCE_DIR}/include/gl_widget_2d/*.h) set(target_name "gl_widget_2d") add_library(${target_name} SHARED ${SRCS} ${HEADERS}) target_link_libraries(${target_name} PRIVATE Qt5::Core Qt5::Widgets Qt5::OpenGL) target_compile_definitions(${target_name} PUBLIC -DGL_WIDGET_2D_LIB) # set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden") set(target_gl_widget_2d ${target_name} PARENT_SCOPE)
The header file of the user-defined widget:
#pragma once // #include <memory> //#include <vector> #include <QBrush> #include <QColor> #include <QFont> #include <QList> #include <QOpenGLWidget> #include <QPen> #include <QWidget> #include "gl_widget_2d_exp_def.h" namespace test::gl_painter { class CloudWidget2DPaintInterface; class CloudWidget2DPaintDash; class CloudWidget2DPaintRect; class CloudWidget2DPaintHorizontalDashLine; class GL_WIDGET_2D_API GLCloudWidget2D : public QOpenGLWidget { friend class CloudWidget2DPaintHorizontalDashLine; friend class CloudWidget2DPaintPoints; friend class CloudWidget2DPaintDash; friend class CloudWidget2DPaintRect; Q_OBJECT public: GLCloudWidget2D(QWidget* parent); ~GLCloudWidget2D() override; void setBackColor(QColor color); void addPaint(CloudWidget2DPaintInterface* paint); const QList<QColor>& colors() const; QList<QColor>& colors(); void setRightToLeft(bool value); void setBottomToTop(bool value); public Q_SLOTS: void animate(); protected: void paintEvent(QPaintEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void resizeEvent(QResizeEvent* event) override; Q_SIGNALS: void signalPaintHit(int pid, int eid, double x, double y); void signalSizeChanged(QSize); protected: QList<CloudWidget2DPaintInterface*> paints_; QList<QColor> colors_; protected: bool right_to_left_{false}, bottom_to_top_{false}; protected: QBrush background_; QBrush circleBrush; QFont textFont; QPen circlePen; QPen textPen; }; } // namespace test::gl_painter
The exported symbol can be found using Dependencies, and show as below:
We can see that other user-defined class and it's member function is exported as
__cdecl
, but thestatic struct QMetaObject ...
does'nt, which is defined in Q_OBJECT.So how to let this symbol mark as exported ?
-
I search Qt's community and stackoverflow, found there are many related posts, but these are not same problem what I am.
I write a user-defined widget inheite from
QOpenGLWidget
, and create a DLL for it usingCMake
: qt-open-glpoint-cloud.The whole error message is:
error LNK2001: 无法解析的外部符号 "public: static struct QMetaObject const test::gl_painter::GLCloudWidget2D::staticMetaObject" (?staticMetaObject@GLCloudWidget2D@gl_painter@test@@2UQMetaObject@@B)
The CMake script list bellow:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) file(GLOB SRCS src/*.cc) file(GLOB HEADERS ${PROJECT_SOURCE_DIR}/include/gl_widget_2d/*.h) set(target_name "gl_widget_2d") add_library(${target_name} SHARED ${SRCS} ${HEADERS}) target_link_libraries(${target_name} PRIVATE Qt5::Core Qt5::Widgets Qt5::OpenGL) target_compile_definitions(${target_name} PUBLIC -DGL_WIDGET_2D_LIB) # set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden") set(target_gl_widget_2d ${target_name} PARENT_SCOPE)
The header file of the user-defined widget:
#pragma once // #include <memory> //#include <vector> #include <QBrush> #include <QColor> #include <QFont> #include <QList> #include <QOpenGLWidget> #include <QPen> #include <QWidget> #include "gl_widget_2d_exp_def.h" namespace test::gl_painter { class CloudWidget2DPaintInterface; class CloudWidget2DPaintDash; class CloudWidget2DPaintRect; class CloudWidget2DPaintHorizontalDashLine; class GL_WIDGET_2D_API GLCloudWidget2D : public QOpenGLWidget { friend class CloudWidget2DPaintHorizontalDashLine; friend class CloudWidget2DPaintPoints; friend class CloudWidget2DPaintDash; friend class CloudWidget2DPaintRect; Q_OBJECT public: GLCloudWidget2D(QWidget* parent); ~GLCloudWidget2D() override; void setBackColor(QColor color); void addPaint(CloudWidget2DPaintInterface* paint); const QList<QColor>& colors() const; QList<QColor>& colors(); void setRightToLeft(bool value); void setBottomToTop(bool value); public Q_SLOTS: void animate(); protected: void paintEvent(QPaintEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void resizeEvent(QResizeEvent* event) override; Q_SIGNALS: void signalPaintHit(int pid, int eid, double x, double y); void signalSizeChanged(QSize); protected: QList<CloudWidget2DPaintInterface*> paints_; QList<QColor> colors_; protected: bool right_to_left_{false}, bottom_to_top_{false}; protected: QBrush background_; QBrush circleBrush; QFont textFont; QPen circlePen; QPen textPen; }; } // namespace test::gl_painter
The exported symbol can be found using Dependencies, and show as below:
We can see that other user-defined class and it's member function is exported as
__cdecl
, but thestatic struct QMetaObject ...
does'nt, which is defined in Q_OBJECT.So how to let this symbol mark as exported ?
@roderick-huang said in Unresolved symbol in user DLL "public: static struct QMetaObject":
PUBLIC DGL_WIDGET_2D_LIB
This does not look right.
-
@roderick-huang said in Unresolved symbol in user DLL "public: static struct QMetaObject":
PUBLIC DGL_WIDGET_2D_LIB
This does not look right.
@Christian-Ehrlicher Thanks. But it's correct.
The following two styles are the same:
target_compile_definitions(${target_name} PUBLIC -DGL_WIDGET_2D_LIB)
target_compile_definitions(${target_name} PUBLIC GL_WIDGET_2D_LIB)
The build log message of mine:
[build] [11/15 26% :: 8.792] "D:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.41.34120\bin\Hostx64\x64\cl.exe" /TP -DGL_WIDGET_2D_LIB -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MESSAGELOGCONTEXT -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_WARN -DSPDLOG_WCHAR_TO_UTF8_SUPPORT -Dgl_widget_2d_EXPORTS -ID:\work\web\qtOpenGLPointCloud2\build\src\gl_widget_2d -ID:\work\web\qtOpenGLPointCloud2\src\gl_widget_2d -ID:\work\web\qtOpenGLPointCloud2\build\src\gl_widget_2d\gl_widget_2d_autogen\include -ID:\work\web\qtOpenGLPointCloud2\system -ID:\work\web\qtOpenGLPointCloud2\3rd\include -ID:\work\web\qtOpenGLPointCloud2\include -external:IC:\Qt\5.15.2\msvc2019_64\include -external:IC:\Qt\5.15.2\msvc2019_64\include\QtCore -external:IC:\Qt\5.15.2\msvc2019_64\.\mkspecs\win32-msvc -external:IC:\Qt\5.15.2\msvc2019_64\include\QtWidgets -external:IC:\Qt\5.15.2\msvc2019_64\include\QtGui -external:IC:\Qt\5.15.2\msvc2019_64\include\QtANGLE -external:IC:\Qt\5.15.2\msvc2019_64\include\QtOpenGL -external:W0 /DWIN32 /D_WINDOWS /W4 /GR /EHsc /O2 /Ox /Ot /Qpar /Gy /Gw /GF /MD /O2 /Ob2 /DNDEBUG -std:c++20 /utf-8 /showIncludes /Fosrc\gl_widget_2d\CMakeFiles\gl_widget_2d.dir\src\gl_cloud_widget_2d.cc.obj /Fdsrc\gl_widget_2d\CMakeFiles\gl_widget_2d.dir\ /FS -c D:\work\web\qtOpenGLPointCloud2\src\gl_widget_2d\src\gl_cloud_widget_2d.cc
-
Please read the documentation I gave you so you can see when this define must be there and when not. You're doing it wrong.
-
Please read the documentation I gave you so you can see when this define must be there and when not. You're doing it wrong.
@Christian-Ehrlicher Thanks. It's my mistake. The compile option should be defined as
PRIVATE
, which means the test exe should useQ_DECL_IMPORT
to link the DLL's symbols -- I'm not clear about the difference betweenPRIVATE
andPUBLIC
inCMake
script.target_compile_definitions(${target_name} PRIVATE -DGL_WIDGET_2D_LIB)
But I'm not understand why no link errors for other symbols exported in the DLL, and why the symbol
static struct QMetaObject const test::gl_painter::GLCloudWidget2D::staticMetaObject
which not marked as__cdecl
can not link ? -
@Christian-Ehrlicher Thanks. It's my mistake. The compile option should be defined as
PRIVATE
, which means the test exe should useQ_DECL_IMPORT
to link the DLL's symbols -- I'm not clear about the difference betweenPRIVATE
andPUBLIC
inCMake
script.target_compile_definitions(${target_name} PRIVATE -DGL_WIDGET_2D_LIB)
But I'm not understand why no link errors for other symbols exported in the DLL, and why the symbol
static struct QMetaObject const test::gl_painter::GLCloudWidget2D::staticMetaObject
which not marked as__cdecl
can not link ?@roderick-huang said in Unresolved symbol in user DLL "public: static struct QMetaObject":
I'm not clear about the difference between PRIVATE and PUBLIC in CMake script.
See https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#target-command-scope
But I'm not understand why no link errors for other symbols exported in the DLL,
They would be appear later I would guess.