【问题标题】:C++/Cx passing delegates to native c++ exception thrownC++/Cx 将委托传递给本机 C++ 引发异常
【发布时间】:2015-08-26 01:31:18
【问题描述】:

我有一个 C++/Cx 库,我需要将 C# 中的回调函数作为指向它的指针传递给该库。

委托在 WinRt 层中声明如下:

public delegate void del(int, enumType, uint, string, int);

C#

void callbackFunction(
            int a,
            enumType b,   //this is public enum class
            uint c,
            String d,
            int e)
{
     tb.Text() = d;
}

Wrc_Component.wrc w = new Wrc_Component.wrc();

del d = new d(callbackFunction);
IntPtr p = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(d);

w.func(p.ToInt32(), "string");

再一次在 func() 的 WinRt 层定义中:

void wrc::func(int ptrToCallback, Platform::String^ str){
    void*p = (void*)ptrToCallBack;
    callBackFunction cb = (callBackFunction)p;
    cb(0,enumType(0),0,"aaaa",0);             //here is exception thrown
}

当然代码简化了一点。 在代码中标记了引发以下异常的行:

App1.exe 中出现“System.Runtime.InteropServices.MarshalDirectiveException”类型的异常,但未在用户代码中处理

附加信息:Windows 运行时委托不能用于 PInvoke 互操作。

我还想提一下,如果我正在调用以相同方式检索的函数,但更简单,它不会引发任何异常。

是什么导致了这个异常?这是因为用户定义的枚举类型吗?

编辑

如果我需要将它进一步传递给 C++ 本地库,据我所知,我无法从 WinRt 中的委托中检索指向函数的指针。

【问题讨论】:

  • 关于您的后续问题,您无法将 C# 委托传递给纯 C++ 库。必须使用 C++/CX 类型。

标签: c# windows-runtime c++-cx


【解决方案1】:

正如 robwirving 所说,您不能只将函数指针作为委托传递给 Windows 运行时组件。

Windows 运行时委托不同于 .NET 委托。要将处理程序从 .NET 传递到 Windows 运行时,您需要有一个 Windows 运行时包装器。在您的情况下,您可以包装委托 del。

    del handler = new del((a, b, c, d, e) =>
    {
       // to change the UI element in a handler, you may need to consider using the CoreDispatcher.
       tb.Text = d;
    });

    w.func(handler, "string");

【讨论】:

    【解决方案2】:

    您不会将委托函数作为本机指针传递。您将它们作为委托类型传递。在你的 C# 中试试这个:

    void callbackFunction(
                int a,
                enumType b,   //this is public enum class
                uint c,
                String d,
                int e)
    {
         tb.Text() = d;
    }
    
    Wrc_Component.wrc w = new Wrc_Component.wrc();
    
    del d = new del(callbackFunction);
    
    w.func(d, "string");
    

    对于您的 WinRT 更改为:

    void wrc::func(del^ myDel, Platform::String^ str){
        if(myDel)
            myDel->Invoke(0, enumType(0),0,"aaaa",0);
    }
    

    我相信我涵盖了所有内容,但我在这里有一篇关于这个主题的完整博客文章:http://www.robwirving.com/2014/07/21/calling-c-methods-c-winrt-components/

    【讨论】:

      【解决方案3】:

      我设法修复了那个异常...

      这个异常的原因是在 Windows 运行时声明的委托不能在 C# 中使用,因此声明和使用 C# 委托解决了这个问题。

      除了问题中的构造之外(当然,委托除外),我能够在我正在使用的所有三层中传递和存储函数指针。

      但是,如果有人在此实现中发现一些可能的危险,请与我们分享以获得更好的代码!

      感谢@Jeffrey Chen 和@robwirving 提供的其他答案。

      【讨论】:

      • 您不认为您应该将我的答案或@Jeffrey Chen 的答案标记为这个问题的答案,而不是发布您自己的回复并选择它作为答案吗?
      • 好吧,我将 Jeffrey Chen 的帖子标记为答案。但我也发布了我的帖子,以回答所有问题。干杯
      猜你喜欢
      • 1970-01-01
      • 2012-07-12
      • 2023-03-25
      • 1970-01-01
      • 2020-07-28
      • 2011-02-27
      • 1970-01-01
      • 2016-10-31
      • 2017-12-27
      相关资源
      最近更新 更多