【发布时间】:2015-08-25 22:36:23
【问题描述】:
我正在构建一个共享库,我希望它能够在不同编译器(如 Windows 上的 MSVC 和 GCC)之间实现 ABI 兼容。我的灵感来自this blog post。我唯一错过的是跨 DLL 边界抛出异常的能力......所以我做了这个小技巧:
MyLibrary.hpp
class Thrower{
static void(*m_thowFunc)(const char*);
public:
static void setThrowFunction(void(*func)(const char*)){
m_thowFunc = func;
}
static void throwException(const char* msg){
m_thowFunc(msg);
}
};
extern "C" {
EXPORT void MyLibrary_setThrowFunction(void(*func)(const char*));
EXPORT void MyLibrary_foo();
}
我的图书馆.cpp
extern "C" {
EXPORT void MyLibrary_setThrowFunction(void(*func)(const char*)){
Thrower::setThrowFunction(func);
}
EXPORT void MyLibrary_foo(){
Thrower::throwException("oops, an error occured...");
}
}
在客户端代码中
void defaultThrowFunction(const char* msg){
throw std::runtime_error(msg);
}
int main(){
MyLibrary_setThrowFunction(&defaultThrowFunction);
try{
MyLibrary_foo();
}catch(std::runtime_error& e){
//handle exception
}
}
这就像一个魅力。我可以在客户端代码中处理从 DLL 抛出的异常(实际上是客户端代码抛出的)。我知道的唯一缺点是我在编译 DLL 时有大量警告,因为“并非所有控制路径都返回值”...
我在这里遗漏了什么吗?这真的是个好主意吗?
【问题讨论】:
-
在 C++11 中使用 [[noreturn]] 删除有关控制路径的警告 (en.cppreference.com/w/cpp/language/attributes)。解决方案看起来不错。
-
如果 C++11 不是一个选项(或者您的编译器版本不支持该功能):有供应商特定的扩展来指示编译器函数不会返回值: MSVC 中的
__declspec(noreturn)和 GCC 中的__attribute__ ((noreturn))。 -
[[noreturn]] 属性将不起作用,因为函数可能想要返回一些东西......例如: int foo(int a){ if(a>0){ return a; }else{ Thrower::throwException("负值");}}
-
对于哪个函数原型编译器会发出警告?
-
我刚刚明白你的意思是在
Thrower::throwException方法上使用[[noreturn]]...确实警告消失了。谢谢!