Ошибки компоновщика сборки CMake при включении службы ADTF в фильтр ADTF
Я получаю странные ошибки компоновщика, которые я не понимаю. Я создал прослушиватель сигналов ADTF, слегка адаптировав исходный код демонстрационной версии: https://support.digitalwerk.net/adtf/v3/adtf_html/page_demo_signal_listener_code.html (для работы кода требовались некоторые #includes). Я создал этот CMakeLists.txt на основе руководства ADTF (https://support.digitalwerk.net/adtf/v3/guides/tutorial_filter_signal.html):
project(ExampleSignalListener
VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}
)
adtf_add_system_service(${PROJECT_NAME}
cExampleSignalListener.h
cExampleSignalListener.cpp
)
find_package(ADTF REQUIRED COMPONENTS systemsdk)
find_package(ADTF REQUIRED COMPONENTS base)
find_package(ADTF REQUIRED COMPONENTS ucom3)
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)
adtf_install_target(${PROJECT_NAME}
toolbox/bin
)
adtf_create_plugindescription(
TARGET
${PROJECT_NAME}
PLUGIN_SUBDIR
toolbox/bin
)
Проект exampleSignalListener строится (в VS2022) и работает в ADTF, как и ожидалось (регистрирует значения сигналов из реестра сигналов на консоли). Теперь я хочу использовать значения этого сигнала в другом фильтре. Я думал, что лучше всего использовать #include <cExampleSignalListener.h>. Здесь возникла первая проблема: по какой-то причине компоновщик другого проекта искал exampleSignalListener.adtfplugin вместо файла .lib:
..\Example_Signal_Listener\Release\ExampleSignalListener.adtfplugin : fatal error LNK1107: invalid or corrupt file: cannot read at 0x308
Я мог бы это исправить, перейдя в «Свойства» > «Компоновщик» > «Ввод» > «Дополнительные зависимости» и вручную изменив .adtfplugin на .lib. Я упоминаю об этом, потому что предполагаю, что это странное поведение связано с моим CMakeLists.txt, и я хотел бы это исправить. Также я могу себе представить, что это актуально для моей текущей, еще нерешенной проблемы:
При связывании .lib и включении заголовка теперь создается новая ошибка, как только я пытаюсь добавить cExampleSignalListener в качестве переменной-члена:
cExampleSignalProvider.obj : error LNK2019: unresolved external symbol "public: __cdecl cExampleSignalListener::cExampleSignalListener(void)" (??0cExampleSignalListener@@QEAA@XZ) referenced in function "public: __cdecl cExampleSignalProvider::cExampleSignalProvider(void)" (??0cExampleSignalProvider@@QEAA@XZ)
Example_Signal_Provider\Release\ExampleSignalProvider.adtfplugin : fatal error LNK1120: 1 unresolved externals
По какой-то причине он находит файл заголовка с определениями, но не может сопоставить его с реализациями исходных файлов (это работает, если я добавляю реализацию непосредственно в заголовок, а затем жалуюсь, что все остальные функции файла заголовка неразрешены).
Дополнительный код, если это поможет решить проблему: cExampleSignalListener.h:
#pragma once
#include <plugins/signal_listening_intf.h>
#include <adtfsystemsdk/adtf_service.h>
#include <adtfbase/adtf_plugin.h>
#include <adtfbase/adtf_runtime.h>
class cSignalDumper : public adtf::services::ant::ISignalListening::ISignalListener
{
public:
cSignalDumper(const char* strSignalName);
public:
void SignalUpdated(adtf::services::ant::ISignalRegistry::tSignalID nSignalID, const adtf::services::ant::ISignalRegistry::tSignalValue& sValue) override;
private:
A_UTILS_NS::cString m_strSignalName;
};
class cExampleSignalListener : public adtf::system::ant::cADTFService, public adtf::services::ant::ISignalListening::ISignalsListener
{
public:
ADTF_CLASS_ID_NAME(cExampleSignalListener, "example_signal_listener.service.adtf.cid", "Example Signal Listener");
ADTF_CLASS_DEPENDENCIES(
REQUIRE_INTERFACE(adtf::services::ISignalListening),
PROVIDE_INTERFACE(adtf::services::ISignalListening)
);
cExampleSignalListener();
public: // overrides cService
virtual tResult ServiceInit() override;
virtual tResult ServiceShutdown() override;
public: // overrides ISignalListening::ISignalsListener
virtual void SignalAdded(const adtf::services::ant::ISignalRegistry::tSignalAttributes& sSignalAttributes) override;
virtual void SignalRemoved(const adtf::services::ant::ISignalRegistry::tSignalAttributes& sSignalAttributes) override;
private:
adtf::ucom::ant::object_ptr<adtf::services::ant::ISignalListening> m_pSignalListening;
std::unordered_map<adtf::services::ISignalRegistry::tSignalID, std::unique_ptr<cSignalDumper>> m_oDumper;
};
cExampleSignalProvider.h (файл, содержащий прослушиватель сигналов):
/**
*
* ADTF Tutorial filter for data processing
*
*/
#pragma once
// Include all necessary headers from the ADTF SDK
#include <adtffiltersdk/adtf_filtersdk.h>
#include <plugins/signal_registry_intf.h>
#include <cExampleSignalListener.h>
#include <adtffiltersdk/filter.h>
#include <adtfsystemsdk/kernel_timer.h>
#include <adtf_mediadescription.h>
#include <adtf_devicetb_sdk.h>
#include <mutex>
#include <unordered_set>
// For simplicity use the necessary namespaces
using namespace adtf::util;
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::filter;
using namespace adtf::services;
// Now we declare a new class cExampleSignalProvider that
// inherits from cFilter. This will be our Tutorial Filter.
// We also implement IEnabledSignals to react to signal requests.
class cExampleSignalProvider final :
public cFilter,
public ISignalRegistry::ISignalProvider::IEnabledSignals
{
public:
// Inside the class declaration we use an ADTF macro to enable correct treatment
// of class identifier and class name by IClassInfo and the class factories.
ADTF_CLASS_ID_NAME(cExampleSignalProvider,
"ExampleSignalProvider.filter.adtf_guides.cid",
"Example Signal Provider");
// Inform the tools that we require an service that provides the Signal Registry interface.
ADTF_CLASS_DEPENDENCIES(REQUIRE_INTERFACE(adtf::services::ISignalRegistry));
public:
// We implement the constructor where we create our Pins.
cExampleSignalProvider();
// We override the Init method in order to access the Signal Registry Service
// And our instance name.
tResult Init(tInitStage eStage) override;
// We override the ProcessInput method, that we configure to be called each time a trigger occures via one input Pin.
tResult ProcessInput(ISampleReader* pReader,
const iobject_ptr<const ISample>& pSample) override;
// this is called when the first consumer requests a signal to be generated.
tResult EnableSignal(ISignalRegistry::tSignalID nSignalID) override;
// this is called when the last consumer cancels its requests for a signal to be generated.
tResult DisableSignal(ISignalRegistry::tSignalID nSignalID) override;
private:
// Reader to read data samples from our input Pin.
ISampleReader* m_out;
// this guards concurrent access to m_oEnabledSignals
std::mutex m_oEnabledSignalMutex;
// this store the ids of all requested signals
std::unordered_set<ISignalRegistry::tSignalID> m_oEnabledSignals;
// pointer to our Signal Provider instance.
// must be the first member to destroy.
// every method on this class can still be called until m_pProvider has completed destruction!!!
object_ptr<ISignalRegistry::ISignalProvider> m_pProvider;
// Here the error occurs when adding my cExampleSignalListener
cExampleSignalListener m_signalListener;
};
CMakeLists.txt для exampleSignalProvider:
project(ExampleSignalProvider
VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}
)
adtf_add_filter(${PROJECT_NAME}
cExampleSignalProvider.h
cExampleSignalProvider.cpp
)
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
find_package(ADTF COMPONENTS filtersdk REQUIRED)
find_package(ADTF COMPONENTS systemsdk REQUIRED)
target_link_libraries(${PROJECT_NAME}
PUBLIC
ExampleSignalListener
)
adtf_install_target(${PROJECT_NAME}
toolbox/bin
)
adtf_create_plugindescription(
TARGET
${PROJECT_NAME}
PLUGIN_SUBDIR
toolbox/bin
)