0

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
   )
Dennix
  • 115
  • 1
  • 10
  • In the [CMake description](https://support.digitalwerk.net/adtf/v3/adtf_html/page_cmake__a_d_t_f_config.html) they note the command `find_package(ADTF)`. I don't see that command in your code. Note, that normally `find_package` call should come **after** the first `project()` call. Calling them before the first `project()` could cause subtle bugs. – Tsyvarev Jun 06 '23 at 12:56
  • I figured this should not make a difference to adding the libraries via target_link_libraries. I just added find_package (edited in) and I still get the very same linker errors – Dennix Jun 06 '23 at 13:11
  • Does calling `adtf_add_system_service` before `find_package(ADTF)` ever work? I would expect that given function is defined (among other things) in `find_package(ADTF)`. – Tsyvarev Jun 06 '23 at 13:17
  • I actually got an error when I moved the find_package calls before adtf_add_system_service: "CMake Error at src/Example_Signal_Provider/CMakeLists.txt:5 (target_include_directories): Cannot specify include directories for target "ExampleSignalProvider" which is not built by this project." – Dennix Jun 06 '23 at 13:44

0 Answers0