gpt4 book ai didi

c++11 - 安全地将回调从托管代码传递到 native 代码

转载 作者:行者123 更新时间:2023-12-04 21:02:22 28 4
gpt4 key购买 nike

我有很多本地类接受某种形式的回调,通常是 boost::signals2::slot -目的。

但为简单起见,让我们假设类:

class Test
{
// set a callback that will be invoked at an unspecified time
// will be removed when Test class dies
void SetCallback(std::function<void(bool)> callback);
}

现在我有一个包装这个原生类的托管类,我想将一个回调方法传递给原生类。
public ref class TestWrapper
{
public:
TestWrapper()
: _native(new Test())
{

}

~TestWrapper()
{
delete _native;
}
private:
void CallbackMethod(bool value);
Test* _native;
};

现在通常我会做的是:
  • 在托管包装器中声明一个方法,即我想要的回调。
  • 为此方法创建一个托管委托(delegate)对象。
  • 使用 GetFunctionPointerForDelegate 获取指向函数的指针
  • 将指针转换到正确的签名
  • 将指向 native 类的指针作为回调传递。
  • 我还让代理保持事件状态,因为我担心它会被垃圾收集,并且我会有一个悬空的函数指针(这个假设是否正确?)

  • 这看起来像这样:
    _managedDelegateMember = gcnew ManagedEventHandler(this, &TestWrapper::Callback);
    System::IntPtr stubPointer = Marshal::GetFunctionPointerForDelegate(_managedDelegateMember);
    UnmanagedEventHandlerFunctionPointer functionPointer = static_cast<UnmanagedEventHandlerFunctionPointer >(stubPointer.ToPointer());
    _native->SetCallback(functionPointer);

    我想减少代码量并且不必执行任何强制转换或声明任何委托(delegate)类型。我想使用没有委托(delegate)的 lambda 表达式。

    这是我的新方法:
    static void SetCallbackInternal(TestWrapper^ self)
    {
    gcroot<TestWrapper^> instance(self);
    self->_native->SetCallback([instance](bool value)
    {
    // access managed class from within native code
    instance->Value = value;
    }
    );
    }
  • 声明一个接受 this 的静态方法为了能够使用 C++11 lambda。
  • 使用 gcroot 捕获 lambda 中的托管类,并在 lambda 处于事件状态时延长其生命周期。
  • 没有类型转换,没有额外的委托(delegate)类型或成员,最小的额外分配。

  • 问题:
    是这种方法吗 保险箱 ?我担心我遗漏了一些东西,这可能会在某些意外情况下导致内存泄漏/未定义行为。

    编辑:

    这种方法导致 MethodAccessException当 lambda 调用其托管包装类的私有(private)方法时。似乎这种方法至少必须是 internal .

    最佳答案

    我认为您不应该使用 gcroot 而是使用共享指针。只要有人在使用共享指针,就可以使对象保持事件状态。

    您还应该在整个代码中使用更多的 c++ 样式,将原始指针替换为智能指针和模板而不是 std::function(可以将 lambda 存储在编译时类型中)。

    例如使用您发布的代码:

    class Test
    {
    // set a callback that will be invoked at an unspecified time
    // will be removed when Test class dies
    template <class T>
    void SetCallback(T callback); // Replaced std::function<void(bool)> with T
    }

    public ref class TestWrapper
    {
    public:
    TestWrapper()
    : _native()
    {}
    private:
    void CallbackMethod(bool value);
    std::unique_ptr<Test> _native; // Replaced Test* with std::unique_ptr<Test>
    };

    关于c++11 - 安全地将回调从托管代码传递到 native 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57177348/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com