I am getting strange linker errors that I do not understand. I created an ADTF Signal Listener by slightly adapting the source of the demo version: https://support.digitalwerk.net/adtf/v3/adtf_html/page_demo_signal_listener_code.html (the code needed some #includes to actually work). I created this CMakeLists.txt based on an ADTF tutorial (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
)
The ExampleSignalListener project builds (in VS2022) and works in ADTF as expected (logging signal values from the signal registry to the console). Now I want to use this signal values in another filter. I thought the way to go would be to #include <cExampleSignalListener.h>. Here the first issue came up, for some reason the linker of the other project looked for ExampleSignalListener.adtfplugin instead of the .lib file:
..\Example_Signal_Listener\Release\ExampleSignalListener.adtfplugin : fatal error LNK1107: invalid or corrupt file: cannot read at 0x308
I could fix this by going to Properties > Linker > Input > Additional Dependencies and changing the .adtfplugin to .lib manually. I am mentioning this, because I assume this odd behaviour stems from my CMakeLists.txt and I would like to fix this. Also I can imagine, that it is relevant for my current still unresolved problem:
While linking the .lib and including the header now builds, I get a new error as soon as I try to add cExampleSignalListener as a member variable:
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
For some reason it finds the header file with the definitions but cannot match it with the source files implementations (it works if I add the implementation directly to the header and then complains about all the other header file functions being unresolved).
Additional Code if this helps resolving the issue: 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 (the file that includes the Signal Listener):
/**
*
* 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 for 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
)