【问题标题】:C# System.NotSupportedException on Marshal.GetFunctionPointerForDelegateMarshal.GetFunctionPointerForDelegate 上的 C# System.NotSupportedException
【发布时间】:2018-11-29 09:42:10
【问题描述】:

我有以下情况: 我有 2 个使用事件与 C# 应用程序通信的 c++ DLL 文件。 C# 应用程序将 Setup() 方法中的函数指针传递给两个文件,这些文件稍后可能会使用此函数指针引发事件。 该应用程序是为 Windows CE 8 和目标框架 Windows Embedded Compact V3.9 (.NET CF 3.9) 编写的。

每个 DLL 通信都封装在一个类中,该类包含一个 Setup() 方法和一个包含所有 DLL 方法的 NativeMethods 子类。两个 DLL 文件都有一个ItemChanged 事件。

示例代码:

private delegate void EventDelegate(int item, int value);
private EventDelegate _eventCallback;
private IntPtr _eventCallbackAddress;

private void OnEvent(int item, int value)
{
  Debug.WriteLine("Item: " + item + ", value: " + value);
}

private void Setup()
{
  _eventCallback = new EventDelegate(OnEvent);
  _eventCallbackAddress = Marshal.GetFunctionPointerForDelegate(_eventCallback); // NotSupportedException
  try
  {
    NativeMethods.Configure(_eventCallbackAddress);
  }
  catch (Exception ex)
  {
    Debug.WriteLine(this, ex.Message);
  }
}

private static class NativeMethods
{
  [DllImport("A.dll", EntryPoint = "Configure", CallingConvention = CallingConvention.WinApi)]
  public static extern void Configure(IntPtr eventCallback);
}

这个 sn-p 在两个类中都使用了,除了 DllImport 引用之外没有任何变化。

我的问题是,在成功传递classA.Setup() 方法后,我在ClassB.Setup() 中的Marshal.GetFunctionPointerForDelegate 方法调用上收到System.NotSupportedException。

MSDN 文档没有帮助,我在互联网上爬网时没有找到更多文档。这就是我来这里的原因。

我观察到在为另一个“测试”委托调用Marshal.GetFunctionPointer 方法时不会发生异常,但它仍然会在Marshal.GetFunctionPointer(_eventCallback) 上抛出

private Delegate testDelegate;
private void Foo() { };

private void Setup()
{
  testDelegate = new Action(Foo);
  IntPtr p = Marshal.GetFunctionPointerForDelegate(testDelegate);

  _eventCallback = new EventDelegate(OnEvent);
  _eventCallbackAddress = Marshal.GetFunctionPointerForDelegate(_eventCallback); // NotSupportedException
  try
  {
    NativeMethods.Configure(_eventCallbackAddress);
  }
  catch (Exception ex)
  {
    Debug.WriteLine(this, ex.Message);
  }

你有什么建议吗?我是不是忘记了什么?

谢谢。

【问题讨论】:

  • sn-ps 中缺少对回答这个问题很重要的 一个 细节。委托的返回类型。咨询我的水晶球:将 bool 更改为 int。
  • 感谢 Hans Passant 指出这一点;返回类型是无效的。我会在描述中更正它。
  • Hmya,你问这个问题已经晚了十年。考虑根本不使用 GetFunctionPointerForDelegate。没有必要,您可以简单地将方法声明为 void Configure(EventDelegate eventCallback)。请注意,您仍然必须将委托对象存储在变量中,以确保它不会被垃圾回收。
  • 谢谢汉斯,我会试试这个,稍后再回来查看更新。

标签: c# dll marshalling .net-cf-3.5 notsupportedexception


【解决方案1】:

ClassB 的签名具有泛型类型参数 <T, U> 以利用基于 int 的泛型枚举作为外部通信接口,假设这些枚举被命名为 RequestItemsResponseItems

在问题分析期间,代码被注释掉,直到检索到一个工作的最小示例。之后逐步取消注释和测试 - 它仍然有效,但在添加泛型类型参数 <T, U> 后,再次抛出异常。

我没想到类签名会对Marshal.GetFunctionPointerFromDelegate方法这样的系统方法调用产生如此大的影响。

工作最小示例:

public ClassA
{
  private delegate void EventDelegate(int item, int value);
  private EventDelegate _eventCallback;
  private IntPtr _eventCallbackAddress;

  private void OnEvent(int item, int value)
  {
    Debug.WriteLine("Item: " + item + ", value: " + value);
  }

  private void Setup()
  {
    _eventCallback = new EventDelegate(OnEvent);
    _eventCallbackAddress = Marshal.GetFunctionPointerForDelegate(_eventCallback);
    try
    {
      NativeMethods.Configure(_eventCallbackAddress);
    }
    catch (Exception ex)
    {
      Debug.WriteLine(this, ex.Message);
    }
  }

  private static class NativeMethods
  {
    [DllImport("A.dll", EntryPoint = "Configure", CallingConvention = CallingConvention.WinApi)]
    public static extern void Configure(IntPtr eventCallback);
  }
}        

不工作的例子 - 添加:

public ClassB<T, U>
{
  //..
}

感谢您的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多