Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking to SHARED Q_OBJECT: unresolved external symbol "public: static struct QMetaObject const A::staticMetaObject"

I am trying to make two QObject libraries, using cmake on windows, where one depend on the other. If i build them both as STATIC libraries it works, but now that i need to build them as SHARED libraries, i keep getting compile errors.

  • error LNK2001: unresolved external symbol "public: static struct QMetaObject const A::staticMetaObject"

I am compiling using Visual Studio 19.

A small example of the problematic code:

First Library:

#include <QObject>
class A: public QObject
{
    Q_OBJECT
public:
    A(const QString& name){}
public Q_SLOTS:
    void ASlot(){}
};

Second Library

#include "A.hpp"
class B: public A {
    Q_OBJECT
public:
    B():A("A"){}
private Q_SLOTS:
    void BSlot(){}
};

CMakeLists.txt:

project(test)
cmake_minimum_required(VERSION 3.10)

set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Modules")

find_package(Qt5Core REQUIRED)
set(CMAKE_AUTOMOC ON)

add_library(A SHARED A.hpp)
target_link_libraries(A ${Qt5Core_LIBRARIES})
set_target_properties(A PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)

add_library(B SHARED B.hpp)
target_link_libraries(B A ${Qt5Core_LIBRARIES})

The code has been verified to work on linux, so i am guessing it might be a problem with how the dll symbols are exported. I have tried using the qt5_wrap_cpp() instead of automoc, but the result does not differ.

I hope someone can help me with the problem.

like image 547
Kasper Høj Lorenzen Avatar asked Nov 14 '25 19:11

Kasper Høj Lorenzen


1 Answers

Don't know if it is still relevant, but I solved the issue by following this official Qt guide for creating shared libraries.

In your case, you should add the follwing lines before declaration of class A:

#if defined(A_EXPORT_SYMBOLS)
#  define A_DLL_EXPORT Q_DECL_EXPORT
#else
#  define A_DLL_EXPORT Q_DECL_IMPORT
#endif

then declare the class A in the following way:

class A_DLL_EXPORT A: public QObject
{
    Q_OBJECT
public:
    A(const QString& name){}
public Q_SLOTS:
    void ASlot(){}
};

and then, add the compile definition to the target A in the cmake configuration:

add_compile_definitions(A PRIVATE A_EXPORT_SYMBOLS)

note that the definition must be PRIVATE in order to have a Q_DECL_EXPORT declaration only in your A dll.

The same goes for class B.

like image 53
Alessandro Muntoni Avatar answered Nov 17 '25 13:11

Alessandro Muntoni



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!