使用同一混合dll的本机c ++模板时,受管部分会引发链接器错误

我试图学习有关C ++ / CLI以便在C ++和C#之间互操作的更多信息。我有3个项目

  • 带有.net 4.7的C#exe
  • C ++ / CLI混合dll和
  • 本机C ++ 17 dll。

我在编译C ++ / CLI项目时遇到问题。我之前已经工作过,所以应该正确设置所有内容,但是由于我做了一些严重的代码更改,因此不再起作用。

在我的C ++ / CLI项目中,我有一个提供一些基本函数调用的类:

// ManagedApi.cpp

public ref class ManagedApi
{
public:
    static void SayHello()
    {
        Bindings::SayHello::invokeIfBound();
    }

    static int Add(int x,int y)
    {
        return Bindings::Add::invokeIfBound(x,y).value_or(-1);
    }

    static void Greet(System::String^ name)
    {
        Bindings::Greet::invokeIfBound(
            msclr::interop::marshal_as<std::string>(name)
        );
    }

    static int accumulate(int x)
    {
        if (!Bindings::accumulate::isBound())
            throw gcnew System::InvalidOperationException("No accumulator bound");

        return Bindings::accumulate::invoke(x);
    }

    static void SayGoodbye()
    {
        Bindings::SayGoodbye::invokeIfBound();
    }
};

这些函数绑定是类型别名:

// Bindings.hpp

namespace Bindings
{
    using SayHello = UnmanagedFunctionBinding<0,void()>;
    using Greet = UnmanagedFunctionBinding<1,void(std::string const&)>;
    using SayGoodbye = UnmanagedFunctionBinding<2,void()>;
    using Add = UnmanagedFunctionBinding<3,int(int,int)>;
    using accumulate = UnmanagedFunctionBinding<4,int(int)>;
}

下面的函数包装基本上是一个std::function单例。

// UnmanagedFunctionBinding.hpp

template <auto ID,typename TReturn,typename... TArgs>
class UnmanagedFunctionBinding<ID,TReturn(TArgs...)>
{
public:
    UnmanagedFunctionBinding() = delete;

    using FunctionType = std::function<TReturn(TArgs...)>;
    GLUE_API static constexpr decltype(ID) Id = ID;

    GLUE_API static bool isBound() noexcept
    {
        return static_cast<bool>(s_func);
    }

    GLUE_API static TReturn invoke(TArgs... args)
    {
        return s_func(std::forward<TArgs>(args)...);
    }

    GLUE_API static auto invokeIfBound(TArgs... args) ->
        std::conditional_t<std::is_same_v<TReturn,void>,void,std::optional<TReturn>>
    {
        if constexpr (std::is_same_v<TReturn,void>)
        {
            if (isBound())
                s_func(std::forward<TArgs>(args)...);
        }
        else
        {           
            return isBound()
                ? std::make_optional(s_func(std::forward<TArgs>(args)...))
                : std::nullopt; 
        }
    }

    GLUE_API static void bind(std::function<TReturn(TArgs...)> func) noexcept
    {
        s_func = std::move(func);
    }

    GLUE_API static void unbind() noexcept
    {
        s_func = nullptr;
    }

private:
    static FunctionType s_func;
};

在模仿类似的行为(基本上访问了用作不同功能的查找表的全局映射)之前,我使用了名称空间功能,但效果很好。但是由于我移到类而不是函数,所以我在混合dll中收到链接器错误。上面的所有代码都位于同一个C ++ / CLI项目中。

自从我进入链接阶段以来,编译似乎一直有效,但显然我的ManagedApi.obj在这里遇到了一些麻烦:

  

ManagedApi.obj:错误LNK2020:无法解析的令牌(0A00022A)“专用:静态类std :: function胶水:: UnmanagedFunctionBinding :: s_func“(?s_func @?$ UnmanagedFunctionBinding @ $ MH02 $$ A6AHHH @ Z $$ V @ Glue @@ 0V?$ function @ $$ A6AHHH @ Z @ std @@ A)

  

ManagedApi.obj:错误LNK2001:未解析的外部符号“私人:静态类std :: function胶水:: UnmanagedFunctionBinding :: s_func”(?s_func @?$ UnmanagedFunctionBinding @ $ MH01 $ $ A6AXXZ $$ V @ Glue @@ 0V?$ function @ $$ A6AXXZ @ std @@ A)

仅举几例。在这一点上,我没有跨越任何DLL边界,所以我不知道为什么不应该链接此代码。我以为可能有一些特殊的C ++ / CLI机制,所以我添加了一个本地源文件(Bindings.cpp),在其中我明确实例化了所有使用的模板(包括std::function和{{1} }。但是现在,此源文件引发了相同的链接器错误。为什么?

从错误消息中我发现它与std::string成员有关系,但是我不知道问题出在哪里。当它们似乎解决相同的问题时,为什么会有两个不同的错误UnmanagedFunctionBinding::s_funcLNK2020

woodfishzgw1234 回答:使用同一混合dll的本机c ++模板时,受管部分会引发链接器错误

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3084637.html

大家都在问