有用的C库不提供C++绑定(bind)并不少见。从C++调用C很容易,但是在其他问题中,C++项目可能需要异常,而不是数字错误返回值。
是否有任何特定的约定或技巧可转换为异常,而每个函数调用中不包含if
和throw
?
我写了这个解决方案,用于包装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()
。关于c++ - 最好的抽象包装带有异常的C错误处理的最佳方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56995824/