Проблема с подключением динамической библиотеки и получением указателя на метод с использованием QLibrary
Как правильно подключить динамическую библиотеку к проекту и использовать определенные методы из нее с использованием класса QLibrary
?
У меня есть следующий код, в котором я пытаюсь подключить динамическую библиотеку и вызвать определенный метод из нее:
bool AgentManager::registerAgent(AgentSettings &settings) {
QLibrary myLibrary("/opt/goinfre/werewolf/Documents/github/MonitoringSystem/agents/cpu_agent/libcpu_agent");
if (!myLibrary.load()) {
qDebug() << "Ошибка при загрузке библиотеки";
qDebug() << myLibrary.errorString();
return false;
}
using fn = Agent* (*)(const AgentSettings&);
fn newbie = reinterpret_cast<fn>(myLibrary.resolve("create"));
if (!newbie) {
qDebug() << "Ошибка при регистрации агента";
qDebug() << myLibrary.errorString();
return false;
}
Agent * agent = newbie(settings);
if (!agent) {
qDebug() << "Ошибка при создании агента";
return false;
}
beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
m_data.push_back(agent);
endInsertRows();
return true;
}
Используется класс AgentManager
, который пытается загрузить динамическую библиотеку libcpu_agent
и вызвать метод create
из этой библиотеки. Однако, при вызове myLibrary.resolve("create")
я получаю nullptr
и выводится сообщение об ошибке "Ошибка при регистрации агента". AgentManager
знает только класс Agent
и должен использовать его как интерфейс для вызова getMetrics
Как я могу правильно подключить динамическую библиотеку и получить указатель на нужный метод? Что может быть причиной возникновения этой ошибки?
cpu_agent.h
:
#pragma once
#include "agent.h"
class CpuAgent final : public Agent {
public:
CpuAgent() = default;
explicit CpuAgent(const AgentSettings &settings);
~CpuAgent() = default;
static Agent * create(const AgentSettings &settings);
virtual const QHash<QString, Metric> & getMetrics() const override final;
};
agent.h
:
#pragma once
#include "agent_settings.h"
class Agent {
public:
Agent() = default;
explicit Agent(const AgentSettings &settings);
explicit Agent(const Agent & other) = delete;
explicit Agent(Agent && other) = delete;
virtual ~Agent() = default;
Agent & operator=(const Agent & other) = delete;
Agent & operator=(Agent && other) = delete;
virtual const QHash<QString, Metric> & getMetrics() const = 0;
const AgentSettings & getSettings() const;
AgentSettings & getSettings();
protected:
AgentSettings m_settings;
};
agent_settings.h
:
#pragma once
#include <QDir>
#include <QElapsedTimer>
#include <QHash>
#include <QPair>
#include <QString>
#include <QTime>
#include <QVariant>
enum class ComparisonOperator {
kLessThan = 0,
kLessThanOrEqualTo,
kEqualTo,
kGreaterThanOrEqualTo,
kGreaterThan
};
struct Metric {
QVariant value;
ComparisonOperator op;
QVariant comparisonValue;
};
struct AgentSettings {
bool m_enabled;
QString m_name;
QString m_type;
QTime m_interval;
QFileInfo m_config;
QElapsedTimer m_timer;
QHash<QString, Metric> m_metrics;
};
CMake для сборки динамической библиотеки:
cmake_minimum_required(VERSION 3.15)
project(cpu_agent VERSION 1.0.0 LANGUAGES CXX)
find_package(Qt6 6.2 COMPONENTS Core REQUIRED)
set(HEADERS
cpu_agent.h
../agent/agent.h
../../settings/agent/agent_settings.h
)
set(SOURCES
cpu_agent.cc
../agent/agent.cc
../../settings/agent/agent_settings.cc
)
set(PROJECT_SOURCES
${HEADERS}
${SOURCES}
)
add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../agent
${CMAKE_CURRENT_SOURCE_DIR}/../../settings/agent
)
set_target_properties(${PROJECT_NAME} PROPERTIES
# PREFIX ""
# SUFFIX .so
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../../agents/${PROJECT_NAME}"
)
target_compile_features(${PROJECT_NAME}
PUBLIC
cxx_std_17
)
target_compile_options(
${PROJECT_NAME}
PRIVATE
# -Wall
# -Werror
# -Wextra
# -Wpedantic
# -fsanitize=address
)
target_link_options(
${PROJECT_NAME}
PRIVATE
# -fsanitize=address
)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt6::Core)
# Копируем файл настроек в выходную директорию
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/setting.conf
${CMAKE_CURRENT_SOURCE_DIR}/../../../agents/${PROJECT_NAME}
)
➜ MonitoringSystem git:(develop) ✗ nm -C agents/cpu_agent/libcpu_agent.dylib
0000000000003f34 s GCC_except_table15
0000000000003f00 s GCC_except_table2
0000000000003f10 s GCC_except_table29
0000000000003f24 s GCC_except_table6
U __Unwind_Resume
U QArrayData::deallocate(QArrayData*, long long, long long)
0000000000003a00 T QArrayData::ref()
0000000000003720 T QArrayData::deref()
0000000000003160 T int QAtomicOps<int>::loadRelaxed<int>(std::__1::atomic<int> const&)
0000000000003a70 T bool QAtomicOps<int>::ref<int>(std::__1::atomic<int>&)
0000000000003220 T bool QAtomicOps<int>::deref<int>(std::__1::atomic<int>&)
0000000000003100 t QHashPrivate::Data<QHashPrivate::Node<QString, Metric> >::~Data()
0000000000003380 t QHashPrivate::Data<QHashPrivate::Node<QString, Metric> >::~Data()
0000000000003560 t QHashPrivate::Node<QString, Metric>::~Node()
0000000000003580 t QHashPrivate::Node<QString, Metric>::~Node()
0000000000003540 T QHashPrivate::Span<QHashPrivate::Node<QString, Metric> >::Entry::node()
0000000000003450 T QHashPrivate::Span<QHashPrivate::Node<QString, Metric> >::freeData()
0000000000003410 t QHashPrivate::Span<QHashPrivate::Node<QString, Metric> >::~Span()
0000000000003430 t QHashPrivate::Span<QHashPrivate::Node<QString, Metric> >::~Span()
0000000000003780 t AgentSettings::AgentSettings(AgentSettings const&)
00000000000037f0 t AgentSettings::AgentSettings(AgentSettings const&)
0000000000002f80 t AgentSettings::~AgentSettings()
0000000000002fb0 t AgentSettings::~AgentSettings()
00000000000036f0 T QTypedArrayData<char16_t>::deallocate(QArrayData*)
00000000000039d0 T QArrayDataPointer<char16_t>::ref()
0000000000003690 T QArrayDataPointer<char16_t>::deref()
0000000000003950 t QArrayDataPointer<char16_t>::QArrayDataPointer(QArrayDataPointer<char16_t> const&)
0000000000003980 t QArrayDataPointer<char16_t>::QArrayDataPointer(QArrayDataPointer<char16_t> const&)
0000000000003620 t QArrayDataPointer<char16_t>::~QArrayDataPointer()
0000000000003640 t QArrayDataPointer<char16_t>::~QArrayDataPointer()
00000000000036d0 T QArrayDataPointer<char16_t>::operator->()
0000000000003a30 T QBasicAtomicInteger<int>::ref()
0000000000003140 T QBasicAtomicInteger<int>::deref()
00000000000037b0 T Agent::getSettings()
0000000000003740 T Agent::Agent(AgentSettings const&)
0000000000002fa0 t Agent::~Agent()
0000000000002fa0 t Agent::~Agent()
0000000000002f50 t Agent::~Agent()
00000000000038f0 t QHash<QString, Metric>::QHash(QHash<QString, Metric> const&)
0000000000003bc0 t QHash<QString, Metric>::QHash(QHash<QString, Metric> const&)
0000000000003000 t QHash<QString, Metric>::~QHash()
0000000000003040 t QHash<QString, Metric>::~QHash()
00000000000035b0 t Metric::~Metric()
00000000000035d0 t Metric::~Metric()
00000000000038c0 t QString::QString(QString const&)
0000000000003920 t QString::QString(QString const&)
0000000000003020 t QString::~QString()
0000000000003600 t QString::~QString()
0000000000002e60 T CpuAgent::create(AgentSettings const&)
0000000000002e30 T CpuAgent::CpuAgent(AgentSettings const&)
0000000000002df0 T CpuAgent::CpuAgent(AgentSettings const&)
0000000000002f00 t CpuAgent::~CpuAgent()
0000000000002ee0 t CpuAgent::~CpuAgent()
0000000000002f30 t CpuAgent::~CpuAgent()
U QVariant::~QVariant()
U QFileInfo::QFileInfo(QFileInfo const&)
U QFileInfo::~QFileInfo()
00000000000036e0 T QtPrivate::QPodArrayOps<char16_t>::destroyAll()
0000000000003c00 T QtPrivate::RefCount::ref()
00000000000030b0 T QtPrivate::RefCount::deref()
0000000000003120 T QBasicAtomicInteger<int>::loadRelaxed() const
00000000000037d0 T Agent::getSettings() const
0000000000002ec0 T CpuAgent::getMetrics() const
0000000000003180 t std::__1::__atomic_base<int, false>::load(std::__1::memory_order) const
0000000000003c40 t std::__1::__atomic_base<int, false>::load(std::__1::memory_order) const
0000000000003ad0 t std::__1::__atomic_base<int, true>::fetch_add(int, std::__1::memory_order)
0000000000003280 t std::__1::__atomic_base<int, true>::fetch_sub(int, std::__1::memory_order)
0000000000003d10 t std::__1::__atomic_base<int, true>::fetch_sub(int, std::__1::memory_order)
0000000000003250 t std::__1::__atomic_base<int, true>::operator--()
0000000000003ce0 t std::__1::__atomic_base<int, true>::operator--()
0000000000003aa0 t std::__1::__atomic_base<int, true>::operator++()
00000000000031b0 t int std::__1::__cxx_atomic_load<int>(std::__1::__cxx_atomic_base_impl<int> const*, std::__1::memory_order)
0000000000003c70 t int std::__1::__cxx_atomic_load<int>(std::__1::__cxx_atomic_base_impl<int> const*, std::__1::memory_order)
0000000000003b00 t int std::__1::__cxx_atomic_fetch_add<int>(std::__1::__cxx_atomic_base_impl<int>*, int, std::__1::memory_order)
00000000000032b0 t int std::__1::__cxx_atomic_fetch_sub<int>(std::__1::__cxx_atomic_base_impl<int>*, int, std::__1::memory_order)
0000000000003d40 t int std::__1::__cxx_atomic_fetch_sub<int>(std::__1::__cxx_atomic_base_impl<int>*, int, std::__1::memory_order)
U std::terminate()
0000000000004040 S typeinfo for Agent
0000000000004050 S typeinfo for CpuAgent
0000000000003f4e S typeinfo name for Agent
0000000000003f44 S typeinfo name for CpuAgent
0000000000004068 s vtable for Agent
0000000000004018 S vtable for CpuAgent
U vtable for __cxxabiv1::__class_type_info
U vtable for __cxxabiv1::__si_class_type_info
U operator delete[](void*)
U operator delete(void*)
U operator new(unsigned long)
0000000000003550 t ___clang_call_terminate
U ___cxa_begin_catch
U ___cxa_pure_virtual
U ___gxx_personality_v0
00000000000080d8 d __dyld_private
U dyld_stub_binder