Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to abstract wrapping C error handling with exceptions

Tags:

c++

exception

It is not uncommon for a useful C library to not provide C++ bindings. It's easy to call C from C++, but among other issues, a C++ project probably wants exceptions, rather than numerical error return values.

Is there any particular convention or trick for converting to exceptions without including an if and throw with each function call?

I wrote this solution for wrapping gphoto2 calls. Having to wrap the templated function in a macro is awkward (but the function name is kind of important for error messages; the logic here is similar to perror).

Is there a better technique, or any open source project that does this particularly well?

#include <gphoto2/gphoto2.h>
#include <string>

class Gphoto2Error : public std::exception {
  private:
    std::string message;

  public:
    Gphoto2Error(std::string func, int err) {
        message = func + ": " + std::string(gp_result_as_string(err));
    }
    const char *what() const throw() {
        return message.c_str();
    }
};

template <typename F, typename... Args>
void _gpCall(const char *name, F f, Args... args) {
    int ret = f(args...);
    if (ret != GP_OK) {
        throw Gphoto2Error(name, ret);
    }
}
#define gpCall(f, ...) ((_gpCall(#f, ((f)), __VA_ARGS__)))

int main() {
    GPContext *ctx = gp_context_new();
    Camera *camera;
    gpCall(gp_camera_new, &camera);
    gpCall(gp_camera_init, camera, ctx);
}
like image 879
Ian D. Scott Avatar asked Jul 11 '19 19:07

Ian D. Scott


People also ask

How errors and exceptions are handled in C?

The C programming language does not support exception handling nor error handling. It is an additional feature offered by C. In spite of the absence of this feature, there are certain ways to implement error handling in C. Generally, in case of an error, most of the functions either return a null value or -1.

Does C support exception handling?

C does not provide direct support for error handling (also known as exception handling). By convention, the programmer is expected to prevent errors from occurring in the first place, and test return values from functions.


1 Answers

Since it’s possible (in practice, via __PRETTY_FUNCTION__ or typeid) to recover the name of a function to which a template parameter refers, I would (in C++17) write

template<auto &F,class ...AA>
void gpCall(AA &&...aa) {
  if(int ret=f(aa...); ret!=GP_OK)
    throw Gphoto2Error(/* … */,ret);
}
int main() {
  GPContext *ctx = gp_context_new();
  Camera *camera;
  gpCall<gp_camera_new>(&camera);
  gpCall<gp_camera_init>(camera, ctx);
  return 0;
}

The expression to obtain the function name is implementation-dependent, but a basic approach that produces usable results (albeit with extra text) in many cases is to add

#include<typeinfo>
template<auto&> Symbol;

and write typeid(Symbol<F>).name().

like image 63
Davis Herring Avatar answered Sep 24 '22 22:09

Davis Herring