gpt4 book ai didi

c# - 统一处理非托管 API 中的错误代码

转载 作者:行者123 更新时间:2023-11-30 12:37:07 25 4
gpt4 key购买 nike

我正在围绕一个相当大的非托管 API 编写一个包装器。几乎每个导入的方法在失败时都会返回一个常见的错误代码。现在,我正在这样做:

ErrorCode result = Api.Method();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}

这很好用。问题是,我有太多的非托管方法调用,以至于这变得非常令人沮丧和重复。所以,我尝试切换到这个:

public static void ApiCall(Func<ErrorCode> apiMethod) {
ErrorCode result = apiMethod();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}
}

这让我可以将所有这些调用缩减为一行:

Helper.ApiCall(() => Api.Method());

然而,这有两个直接的问题。首先,如果我的非托管方法使用 out 参数,我必须首先初始化局部变量,因为方法调用实际上是在委托(delegate)中进行的。我希望能够简单地声明一个 out 目标而不对其进行初始化。

其次,如果抛出异常,我真的不知道它是从哪里来的。调试器跳转到 ApiCall 方法,堆栈跟踪仅显示包含对 ApiCall 的调用的方法,而不是委托(delegate)本身。由于我可以在一个方法中进行许多 API 调用,这使得调试变得困难。

然后我考虑使用 PostSharp 来包装所有带有错误代码检查的非托管调用,但我不确定如何使用 extern 方法来完成。如果它最终只是为它们中的每一个创建一个包装器方法,那么我会遇到与 ApiCall 方法相同的异常问题,对吗?另外,如果它只存在于已编译的程序集中,调试器如何知道如何向我显示代码中抛出异常的位置?

接下来,我尝试实现一个自定义编码(marshal)拆收器,它将拦截 API 调用的返回值并检查那里的错误代码。遗憾的是,您不能将自定义编码(marshal)拆收器应用于返回值。但我认为,如果可行的话,这将是一个非常干净的解决方案。

[return:
MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ApiMethod))]
public static extern ErrorCode Method();

现在我完全没有想法了。我还有哪些其他方法可以处理此问题?

最佳答案

关注 ErrorHandler 来自 Visual Studio 2010 SDK 的类。它存在于早期版本中,但新版本具有 CallWithCOMConvention(Action) ,这可能会证明很有值(value),具体取决于您的 API 与其他托管代码的交互方式。

在可用的方法中,我建议实现以下方法:

  • Succeeded(int)
    ( Failed() 就是 !Succeeded() ,所以你可以跳过它)

  • ThrowOnFailure(int)
    (为您的返回码抛出一个适当的异常)

  • CallWith_MyErrorCode_Convention(Action)CallWith_MyErrorCode_Convention(Func<int>)
    (如 CallWithCOMConvention ,但用于您的错误代码)

  • IsCriticalException(Exception)
    (由 CallWith_MyErrorCode_Convention 使用)

关于c# - 统一处理非托管 API 中的错误代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1882283/

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