gpt4 book ai didi

c# - 包装一个在 c# 中实现回调的 native 库

转载 作者:行者123 更新时间:2023-11-30 18:00:45 26 4
gpt4 key购买 nike

我有一个 Visual Studio 2008 C# .NET 3.5 类,它提供对 native 库的访问。该库有一个 Register 方法,允许用户指定将在某些事件上激活的回调。我在下面提供了一个 C# 实现:

internal class MyLibHandle : SafeHandleZeroOrMinusOneIsInvalid { /*...*/ }

internal static class NativeMethods
{
public delegate void OnSomeEventDelegate (FOO foo, IntPtr user);

[DllImport("MyLib.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool MyLib_Register(MyLibHandle handle, OnSomeEventDelegate callback, IntPtr user);
}

public class MyWrappedLib : IDisposable
{
private MyLibHandle handle_;

private event EventHandler<OnSomeEventArgs> some_event_int_;

public event EventHandler<OnSomeEventArgs> SomeEvent
{
add
{
if (some_event_int_ == null)
{
if (!NativeMethods.MyLib_Register(handle_, ReceivedSomeEvent, IntPtr.Zero))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
some_event_int_ += value;
}
remove
{
some_event_int_ -= value;
if (some_event_int_ == null)
{
if (!NativeMethods.MyLib_DeRegister(handle_, -1))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}

private void ReceivedSomeEvent(FOO foo, IntPtr user)
{
OnSomeEvent(new OnSomeEventArgs() { foo = foo });
}

protected virtual void OnBeacon(OnSomeEventArgs args)
{
EventHandler<OnSomeEventArgs> evt = some_event_int_;
if (evt != null)
evt(this, args);
}
}

这行得通,但我收到了一些听起来不祥的警告

warning : CA1065 : Microsoft.Design : 'MyWrappedLib.SomeEvent.add(EventHandler<OnSomeEventArgs>)' creates an exception of type 'Win32Exception', an exception type that should not be raised in this type of method.

warning : CA2122 : Microsoft.Security : 'MyWrappedLib.SomeEvent.add(EventHandler<OnSomeEventArgs>)' calls into 'Marshal.GetLastWin32Error()' which has a LinkDemand. By making this call, 'Marshal.GetLastWin32Error()' is indirectly exposed to user code.

处理这种情况的建议方法是什么?我应该创建一个方法来处理事件订阅而不是传统的添加吗?消除;访问器(accessor)?

谢谢

最佳答案

对于事件访问器,允许以下异常类型:

  • System.InvalidOperationException 和所有衍生品(包括System.ObjectDisposedException)

  • System.NotSupportedException 和所有衍生物

  • ArgumentException 和派生词

为什么本地方法会返回false?会不会跟一些外在条件有关,还是传递了无效参数的结果?

所以我会将 Win32Exception 包装为 InvalidOperationException 的内部,或 ArgumentException,具体取决于您的情况。

第二个警告(CA2122)是关于安全的——它警告 Marshal.GetLastWin32Error 执行安全检查,而你的代码没有。此安全检查仅执行一次,在第一次通话时。此后的所有调用均未验证访问权限,出于性能原因。所以理论上,第一个电话可以由受信任的用户,所有进一步的调用都不会受到限制。

您需要使用以下属性装饰您的事件处理程序:

[SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]

(它将检查代码是否有权调用托管代码)如果您的应用程序不关心安全性,或者取消此警告。

细节在this question中有很大的解释。 .

关于c# - 包装一个在 c# 中实现回调的 native 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9774593/

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