I have the problem with reusing my shared libraries on windows, because of microsoft declspec "feature". In the shared library I have the class using QT::RemoteObjects autogenerated SOURCE or REPLICA classes, and I am not able to use signal-slot features anywhere outside my library code. Consider this small example:
CMakeLists.txt
cmake_minimum_required(VERSION 3.11.0)
project(QtSymbolsProblem CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set (CMAKE_CXX_STANDARD 17)
find_package(Qt5 COMPONENTS RemoteObjects Core REQUIRED)
qt5_generate_repc(GENERATED PanelInterface.rep SOURCE)
set_source_files_properties(${GENERATED} PROPERTIES GENERATED TRUE SKIP_AUTOMOC TRUE)
message(STATUS "generated sources: ${GENERATED}")
add_library(SampleProcedure SHARED
Procedure.cpp
${GENERATED}
)
set_target_properties(SampleProcedure PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS ON
)
target_link_libraries(SampleProcedure
Qt5::RemoteObjects
Qt5::Core
)
add_executable(main main.cpp)
target_link_libraries(main PUBLIC SampleProcedure)
Replica definition PanelInterface.rep:
#include <QtCore>
#include <QString>
class PanelInterface
{
PROP(QString foo);
};
Library code:
//// Procedure.hpp
#pragma once
#include <SampleProcedure_export.h>
#include <QObject>
#include <memory>
class PanelInterfaceSimpleSource;
class Procedure {
public:
Procedure();
~Procedure();
PanelInterfaceSimpleSource *panelInterface();
private:
std::unique_ptr<PanelInterfaceSimpleSource> _panel;
};
//// Procedure.cpp
#include "Procedure.hpp"
#include "rep_PanelInterface_source.h"
#include <QObject>
Procedure::Procedure()
: _panel(std::make_unique<PanelInterfaceSimpleSource>()) {}
Procedure::~Procedure() = default;
PanelInterfaceSimpleSource *Procedure::panelInterface() { return _panel.get(); }
Main executable:
#include "Procedure.hpp"
#include "rep_PanelInterface_source.h"
#include <QObject>
#include <iostream>
class Foo : public QObject {
Q_OBJECT
public:
Foo(Procedure &proc) {
QObject::connect( // this is impossible because of missing symbol
proc.panelInterface(), &PanelInterfaceSimpleSource::fooChanged, this,
[](QString str) { std::cout << str.toStdString() << std::endl; });
}
};
int main() {
Procedure proc;
Foo foo(proc);
return 0;
}
#include "main.moc"
In this example PanelInterfaceSimpleSource is a class autogenerated by QT. When I try to connect to one of its signals, linker gives me the error:
main.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const PanelInterfaceSimpleSource::staticMetaObject" (?staticMetaObject@PanelInterfaceSimpleSource@@2UQMetaObject@@B)
In the CMake docs it is mentioned that
For global data symbols, __declspec(dllimport) must still be used when compiling against the code in the .dll.
and I even found some other topics that mention the use of CMake autogenerated export header
include(GenerateExportHeader)
generate_export_header(SampleProcedure)
but this solution will only work with the code that I am allowed to modify.
How should I solve the problem with missing symbol to the class static variable, in the code that was autogenerated by QT?