在 ADTF 筛选器中包含 ADTF 服务时出现 CMake 生成链接器错误

CMake build linker errors when including an ADTF service in an ADTF filter

提问人:Dennix 提问时间:6/6/2023 最后编辑:Dennix 更新时间:6/6/2023 访问量:34

问:

我遇到了我不明白的奇怪的链接器错误。 我通过稍微调整演示版本的源代码来创建一个 ADTF 信号侦听器:https://support.digitalwerk.net/adtf/v3/adtf_html/page_demo_signal_listener_code.html(代码需要一些 #includes 才能实际工作)。 我根据 ADTF 教程 (https://support.digitalwerk.net/adtf/v3/guides/tutorial_filter_signal.html) 创建了这个 CMakeLists.txt

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 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
   )
C++ CMake 链接器错误 ADTF3

评论

0赞 Tsyvarev 6/6/2023
CMake 描述中,他们注意到命令 .我在您的代码中没有看到该命令。请注意,通常该呼叫应在第一次呼叫之后进行。在第一个之前调用它们可能会导致微妙的错误。find_package(ADTF)find_packageproject()project()
0赞 Dennix 6/6/2023
我认为这应该不会对通过target_link_libraries添加库产生影响。我刚刚添加了find_package(编辑),但我仍然收到完全相同的链接器错误
0赞 Tsyvarev 6/6/2023
打电话之前有用吗?我希望给定的功能(除其他外)在 中定义。adtf_add_system_servicefind_package(ADTF)find_package(ADTF)
0赞 Dennix 6/6/2023
当我在adtf_add_system_service之前移动find_package调用时,我实际上遇到了一个错误:“src/Example_Signal_Provider/CMakeLists.txt:5 (target_include_directories) 的 CMake 错误:无法为目标”ExampleSignalProvider“指定包含目录,这不是由此项目构建的。

答: 暂无答案