统一处理错误codeS非托管API中 [英] Uniformly handling error codes in an unmanaged API

查看:144
本文介绍了统一处理错误codeS非托管API中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在写身边一个相当大的非托管API的包装。几乎所有的进口方法失败时返回一个常见的​​错误code。现在,我这样做是:

I'm writing a wrapper around a fairly large unmanaged API. Almost every imported method returns a common error code when it fails. For now, I'm doing this:

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

这工作正常。问题是,我有这么多的非托管方法调用,这变得非常沮丧和重复。所以,我尝试切换到这一点:

This works fine. The problem is, I have so many unmanaged method calls that this gets extremely frustrating and repetitive. So, I tried switching to this:

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

这让我砍掉所有这些调用一个行:

Which allows me to cut down all of those calls to one line:

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

有两次与这眼前的问题,但是。首先,如果我的非托管的方法使用参数,我必须先初始化本地变量,因为该方法调用实际上是一个委托。我想能够简单地声明退出目的地没有初始化它。

There are two immediate problems with this, however. First, if my unmanaged method makes use of out parameters, I have to initialize the local variables first because the method call is actually in a delegate. I would like to be able to simply declare a out destination without initializing it.

第二,如果有异常抛出,我真的不知道它是从哪里来的。调试器跳转到包含调用 ApiCall ApiCall 法和堆栈跟踪只显示方法,而不是委托本身。因为我可以在一个单一的方法很多API调用,这使得调试困难。

Second, if an exception is thrown, I really have no idea where it came from. The debugger jumps into the ApiCall method and the stack trace only shows the method that contains the call to ApiCall rather than the delegate itself. Since I could have many API calls in a single method, this makes debugging difficult.

然后我想过使用PostSharp包装所有错误code。检查非托管的电话,但我不知道如何将与做的extern 方法。如果它最终只是创造了他们每个人的包装方法,那么我将有相同的异常问题,因为与 ApiCall 的方法,对吗?另外,怎么会调试知道如何表达我抛出的异常的网站在我的code,如果它只是在编译的程序集的存在?

I then thought about using PostSharp to wrap all of the unmanaged calls with the error code check, but I'm not sure how that would be done with extern methods. If it ends up simply creating a wrapper method for each of them, then I would have the same exception problem as with the ApiCall method, right? Plus, how would the debugger know how to show me the site of the thrown exception in my code if it only exists in the compiled assembly?

接下来,我想实现一个自定义封,将拦截API调用的返回值,并检查错误code那里。不幸的是,你不能应用自定义封返回值。但我认为那会是一个非常干净的解决方案,如果工作过。

Next, I tried implementing a custom marshaler that would intercept the return value of the API calls and check the error code there. Unfortunately, you can't apply a custom marshaler to return values. But I think that would have been a really clean solution it if had worked.

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

现在,我完全没了主意。什么是一些其他的方式,我可以处理这个?

Now I'm completely out of ideas. What are some other ways that I could handle this?

推荐答案

后续的 的ErrorHandler 类。它存在于早期版本,但新的具有 CallWithCOMConvention(动作) ,这取决于你的API如何与其他管理code相互作用,这可能证明是有价值的。

Follow ErrorHandler class from the Visual Studio 2010 SDK. It existed in earlier versions, but the new one has CallWithCOMConvention(Action), which may prove valuable depending on how your API interacts with other managed code.

可用的方法,我建议实施以下内容:

Of the available methods, I recommend implementing the following:


  • 成功(INT)结果
    失败()只是!成功(),所以你可以跳过)

  • Succeeded(int)
    (Failed() is just !Succeeded(), so you can skip it)

ThrowOnFailure(INT)结果
(一抛出适当的异常你回来code)

ThrowOnFailure(int)
(Throws a proper exception for your return code)

CallWith_MyError code_Convention(动作) CallWith_MyError code_Convention(Func键&LT; INT&GT;)结果
(如 CallWithCOMConvention ,但对你的错误codeS)

CallWith_MyErrorCode_Convention(Action) and CallWith_MyErrorCode_Convention(Func<int>)
(like CallWithCOMConvention, but for your error codes)

IsCriticalException(例外)结果
(使用 CallWith_MyError code_Convention

这篇关于统一处理错误codeS非托管API中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆