抽象包装带有异常的 C 错误处理的最佳方法

Best way to abstract wrapping C error handling with exceptions

本文关键字:错误 处理 最佳 方法 抽象 异常 包装      更新时间:2023-10-16

有用的 C 库不提供C++绑定的情况并不少见。从C++调用 C 很容易,但除其他问题外,C++项目可能需要异常,而不是数字错误返回值。

是否有任何特定的约定或技巧可以在不在每个函数调用中包含ifthrow的情况下转换为异常?

我编写了这个解决方案来包装 gphoto2 调用。必须将模板化函数包装在宏中很尴尬(但函数名称对于错误消息很重要;这里的逻辑类似于perror(。

有没有更好的技术,或者任何开源项目做得特别好?

#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);
}

由于有可能(在实践中,通过 __PRETTY_FUNCTION__typeid (恢复模板参数引用的函数的名称,我会(在 C++17 中(写

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;
}

获取函数名称的表达式依赖于实现,但在许多情况下,产生可用结果(尽管有额外的文本(的基本方法是添加

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

并写typeid(Symbol<F>).name().