美文网首页C++\CLI
本机的回调函数与委托的转换

本机的回调函数与委托的转换

作者: 左图右码 | 来源:发表于2022-04-30 16:15 被阅读0次

    本机的回调一般借助函数指针,managed中的回调一般用委托实现。
    在混合编程中要用到两者的转换。
    其中,重要的是委托到函数指针的转换。
    例如,有native中的class定义如下:

    typedef void(*nativePrinter_t)(char);
    class enumchars
    {
        std::vector<char> chars;
    public:
        enumchars(std::vector<char> const& data) : chars(data){}
        void launch()
        {
            if (m_printer)
            {
                for(auto cur : chars) { m_printer(cur); };
            }
        }
        nativePrinter_t m_printer = nullptr;
    };
    //global native function
    void concreteNativePrinter(char c)
    {
        std::cout << c << "-";
    }
    

    仅仅是打印文本,测试如下:

    int main(array<System::String ^> ^args)
    {
        enumchars ca({'h','e','l','l','o'});
        ca.m_printer = concreteNativePrinter;
        ca.launch();
        return 0;
    }
    

    输出:

    h-e-l-l-o-

    如果想在包装成managed class,则定义如下,包装enumchars指针:

    ref class mclass
    {
        enumchars* ptr;
    public:
        delegate void printstring(char);  //委托的声明中的参数与返回值与函数指针一致
        printstring^ managedPrinter = nullptr;
        mclass()
        {
            ptr = new enumchars({ 'h','e','l','l','o' });  //初始化指针
            
        }
        ~mclass() { delete ptr; }  //删除指针
        !mclass() { ~mclass(); }  
        void launch()
        {
            pin_ptr<printstring^> pin = &managedPrinter;
            auto pF = (nativePrinter_t)Marshal::GetFunctionPointerForDelegate(managedPrinter).ToPointer();
            ptr->m_printer = pF;
            ptr->launch();
        }
        static void printchar(char c)
        {
            System::Console::Write(gcnew System::String(&c));
        }
    };
    ref struct managedPrintStr 
    {
        static void printer(char c)
        {
            System::Console::Write("{0}-"gcnew System::String(&c));
        }
    };
    int main(array<System::String ^> ^args)
    {
        mclass^ c = gcnew mclass;
        c->managedPrinter += gcnew mclass::printstring(mclass::printchar);
        c->managedPrinter += gcnew mclass::printstring(managedPrintStr::printer);
        c->launch();
        return 0;
    }
    

    在launch中:

    void launch()
        {
            pin_ptr<printstring^> pin = &managedPrinter;
            auto pF = (nativePrinter_t)Marshal::GetFunctionPointerForDelegate(managedPrinter).ToPointer();
            ptr->m_printer = pF;
            ptr->launch();
        }
    

    可以看到Marshal::GetFunctionPointerForDelegate将委托转换为指针。再强转为native函数指针。因为委托为句柄,要先进行固定,防止GC的压缩移动。
    输出:

    hh-ee-ll-ll-oo-

    注意,多委托可以转为一个函数指针。C++/CLI里的委托类型都是多委托类型。

    Marshal::GetDelegateForFunctionPointer()则略显多余,因为委托可以直接通过gcnew创建,参数里为本机函数即可。

    相关文章

      网友评论

        本文标题:本机的回调函数与委托的转换

        本文链接:https://www.haomeiwen.com/subject/iesyyrtx.html