【发布时间】:2014-08-27 11:45:32
【问题描述】:
我正在为 C dll 编写一个包装器。为 C# 应用程序包装了各种 C 函数。现在考虑下面包装器的一些简化部分。
public enum ErrorCode
{
OK = 0,
...
...
}
public class AppException: ApplicationException
{
public AppException(ErrorCode errorCode) : base()
{
error = errorCode;
}
public ErrorCode error { get; private set; }
}
public class A
{
public ErrorCode last_ret;
private IntPtr datap;
public A(string filename)
{
last_ret = (ErrorCode)ClibDllFunc1(filename, out datap);
if (last_ret != ErrorCode.OK)
throw new AppException(last_ret);
// go on processing
last_ret = (ErrorCode)ClibDllFunc2(datap);
if (last_ret != ErrorCode.OK)
throw new AppException(last_ret);
}
public void getSize(out int sz)
{
last_ret = (ErrorCode)ClibDllFunc3(datap, out sz);
if (last_ret != ErrorCode.OK)
throw new AppException(last_ret);
}
// ...
// many functions like these, all working by calling c/c++ dll functions
// with different number and types of parameters
}
[DllImport("clibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
static extern internal int ClibDllFunc1(string filename, out IntPtr data);
// ... other C function declarations follow similarly
如您所见,包装器调用了各种 C 函数。所有 C 函数都返回整数作为状态代码(一个错误代码),如果 C 函数失败,包装器必须检查此返回代码并抛出应用程序定义的异常。对于所有 C 函数调用,这必须以完全相同的方式完成。只是函数名和参数改变了,但 3 行调用块是一样的。作为复制/粘贴的 3 行函数调用块,这种形式看起来非常便宜。
在C#中,有没有办法将“调用、检查返回码、抛出异常”循环简化封装成更简单紧凑的方式?
供参考(实际上这是我想做的以简化调用);在 C/C++ 中,我们可以定义一个像这样的宏:
#define SAFE_CALL(call) do{ if((last_ret = (ErrorCode)call) != OK) throw AppException(last_ret); }while(0)
然后这样调用:
SAFE_CALL(ClibDllFunc1(filename, &datap));
SAFE_CALL(ClibDllFunc2(datap));
SAFE_CALL(ClibDllFunc3(datap, &sz));
【问题讨论】:
-
应该能够创建一个将 ClibDllFunc 作为 arg 的函数 SAFE_CALL(返回一个 int 或错误代码)对吗?
-
@NWard 根据下面接受的答案,我做了完全相同的事情。它就像魔术一样工作。它完成了这项工作,但我不明白如何:)