• C++/CLI委托回调




    我们都习惯了在c#中使用事件,但是c++中没有默认的事件机制,所以在编写c++/cli时,这将是一个令人困扰的问题

    在c++中常见的方式是传入一个回调,在特定的时机,通过调用回调函数,执行上层的代码。
    这种方式能够解决一部分场景的问题,但是另外一些场景,比如事件的invok列表,责任链模式都不能实现。
    另外常见的回调对象,要求一次实现多个回调函数,这样容易将各个业务的处理都聚集在同一个回调对象中,不利于解耦。
    在c++/cli中,一种可以参考的处理方式是使用一个托管类对非托管的回调类进行封装。向非托管的回调类传入一个托管类的委托函数后,由委托函数重新引发.NET事件。
    //非托管部分Callback.h
    public class Callback:Public AbstractCallback
    {
    private:
    typedef std::function<void(void)> FooCallback;
    FooCallback _fooCallback;
    public:
    inline void OnFoo() override
    {
    if (_fooCallback)
    {
    _fooCallback();
    }
    }

    inline void SetFooCallback(FooCallback callback)
    {
    _fooCallback=callback;
    }

    }

    //托管部分Wrapper.h
    public ref class Wrapper
    {
    private:
    Callback* _callback;
    delegate void DelegateOnFoo();
    DelegateOnFoo^ _onFoo;
    void InitCallback();
    void OnFoo(){FooEvent(this,gcnew EventArgs())}
    public:
    event EventHandler^ FooEvent;
    }

    //托管部分Wrapper.cpp
    void Wrapper::InitCallback()
    {
    using namespace std;
    _callback = new Callback();
    _onFoo = gcnew DelegateOnFoo(this, &Wrapper::OnFoo);
    IntPtr pvFun1 = Marshal::GetFunctionPointerForDelegate(safe_cast<Delegate^>(_onFoo));
    _callback->SetFooCallback((void(*)(void))pvFun1.ToPointer());
    }

    其中需要注意的几点是:
    我们生成了一个托管的委托,DelegateOnFoo,但是对于非托管的回调来说他只能接受对应的函数指针,因此,需要使用Marshal::GetFunctionPointerForDelegate将其转换为指针
    此时我们得到的是一个IntPtr智能指针对象,我们需要使用ToPointer方法将其转换为void*,然后再强转为参数匹配的(void(*)(void))格式,才能传入非托管方法
    另外,最容易忽略的一点是我们通过_onFoo字段保留了这个委托的引用。对于DelegateOnFoo来说,他是一个.NET对象,由gcnew生成,通过gc进行内存管理,如果不保留引用则随时可能被gc回收。而我们传入非托管对象的是其地址,那么一旦委托被回收,则托管部分运行就会出错。

  • 相关阅读:
    .JS replace方法替换所有字符
    .net framework 4.0,结果还是失败,出现HRESULT 0xc8000222错误代码
    用PowerDesigner15自动将数据库里的表生成ER图
    C#对JSON数据格式的处理
    Type of conditional expression cannot be determined because there is no implicit conversion between 'Common.EnumType.EnumGender' and '<null>'
    如何在string.Format方法中输出大括号({})
    网架构学习笔记
    c#实现javascript中函数escape解码
    Solon 开发,八、注入依赖与初始化
    Solon 开发,七、自定义注解开发汇总
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/13962920.html
Copyright © 2020-2023  润新知