I'm writing a wrapper for a C dll. Various C functions are wrapped for C# applicatons. Now consider some simplified part of the wrapper below.
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
As you can see, the wrapper calls various C functions. All C functions return integer as the status code (an ErrorCode), and the wrapper has to check this return code and throw an application defined exception if the C function fails. This has to be done exactly the same way for all C function calls. Only the function name and parameters change but the 3 line calling-block is the same. It looks really cheap in this form as copy/pasted 3-line blocks of function calls.
In C#, is there a way to simplify and encapsulate the "call, check return code, throw exception" cycle in a simpler and more compact way?
For reference (actually this is what I'd like to do to simplify the calls); in C/C++ we can define a macro like this one:
#define SAFE_CALL(call) do{ if((last_ret = (ErrorCode)call) != OK) throw AppException(last_ret); }while(0)
and call like this:
SAFE_CALL(ClibDllFunc1(filename, &datap));
SAFE_CALL(ClibDllFunc2(datap));
SAFE_CALL(ClibDllFunc3(datap, &sz));