【问题标题】:C++ exception handling in C codesC 代码中的 C++ 异常处理
【发布时间】:2014-06-08 03:27:57
【问题描述】:

当我们用 C 编写程序时,我们可能会调用一些用 C++ 编写但具有 C 接口的库。那么可能会发生当我们调用这些库的时候,会出现C++异常。所以我的问题是我们如何处理这种情况。从 C++ 开发人员的角度来看,我对这个问题更感兴趣。假设我正在开发一个将由 C 程序调用的 C++ 库,我应该停止使用异常并返回错误代码吗?另一种情况是,如果我已经有一个使用异常的完全开发的 C++ 库,我该如何快速转移这个库,只使用错误返回方法?

【问题讨论】:

  • 这不是重复的,因为它没有回答如何处理异常的问题。只有一个答案说“提防异常”,但没有提供任何解决方案。
  • @Lundin,我认为这里没有通用的解决方案。可能的做法是在完全不使用异常的情况下重写代码,或者以使异常不会离开库自己的代码的方式制作包装器,我想?
  • @SingerOfTheFall 我也不知道,我可能会自己破解一些类似的包装器。但我很想知道是否有一些推荐的做法或一些有用的 C++ 语言功能。由于其他问题对提供答案没有帮助,请不要关闭这个问题。
  • 我认为stackoverflow.com/questions/199418/using-c-library-in-c-code这个链接会有帮助,谢谢
  • questionaccepted answer 都没有提到异常。这是怎么复制的?

标签: c++ c exception-handling


【解决方案1】:

异常不会在 C 中捕获,因此如果您想在 C 代码或 C++ 代码中捕获它们,则必须非常小心地编写包装器。

还要确保在 C++ 函数中将函数声明为:

extern "C"

您也可以查看How to mix C and C++

【讨论】:

    【解决方案2】:

    您必须在 C++ 端捕获所有异常并将它们转换为 C 中适当的错误返回,其中可能包括适当的特定错误代码。这并不意味着你停止使用异常——你仍然可以在 C++ 中使用它们——但你不能将它们暴露给 C,它们变成了实现细节。

    一个典型的包装器可以构造如下:

    // thingy-wrapper.h, typically included from C code:
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    // create a typedef visible to C that doesn't expose the layout of
    // the implementation.
    typedef void *thingy_t;
    
    // wrapper for std::string Thingy::get_name()
    char *thingy_get_name(thingy_t t);
    
    #ifdef __cplusplus
    }
    #endif
    
    // thingy-wrapper.cpp, implements the wrapper, compiled with C++:
    
    #include <thingy-wrapper.h>
    #include <thingy.hpp>         // declares Thingy class
    
    char *thingy_get_name(thingy_t t_)
    {
      try {
        Thingy& t = *static_cast<Thingy*>(t_);
        std::string name = t.get_name();
        return strdup(name.c_str());
      }
      catch(...) {
        return NULL;
      }
    }
    

    在这个简单的例子中,thingy_get_name 的调用者可以检测到发生了错误,但无法找出错误的详细信息。更现实的例子是捕获特定异常,并在返回 NULL 之前将 last_error 变量设置为错误代码或消息。 ... 只能作为最后的手段被捕获,并将 last_error 设置为通用的 UNKNOWN_ERROR 值。用于查询最后一个错误的单独 API,例如 thingy_last_error(),将可供更细心的 thingy_get_name() 调用者使用。

    错误和非错误结果之间的分离使得不关心错误原因的代码可以简单地检查它是否收到NULL,同时允许更认真的代码正确传播或报告错误。如果您的库是多线程的,请确保 last_error 使用线程本地存储。

    【讨论】:

      【解决方案3】:

      那么可能会发生,当我们调用这些库时,会出现C++异常。所以我的问题是我们如何处理这种情况。

      C 代码无法处理这种情况。 C 代码无法处理 C++ 异常。

      假设我正在开发一个将由 C 程序调用的 C++ 库,我应该停止使用异常并返回错误代码吗?

      没有。如果您希望 C++ 库被 C++ 代码使用,您应该使用本机 C++ 错误处理。这意味着例外。

      但是,您向 C 代码公开的接口不得引发异常。通常这意味着编写一个适配器层来捕获 C++ 库引发的异常,并将它们转换为错误代码以供 C 代码使用。

      另一种情况是,如果我已经有一个完全开发的使用异常的C++库,我该如何快速转移这个库,只使用错误返回方法?

      这里真的没有捷径。您必须编写将 C++ 异常转换为 C 错误代码的适配器。如果您希望库为 C 和 C++ 使用者公开接口,那么无论如何您都将编写适配器。因此,错误处理方面只是这个适配器需要处理的另一件事。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-22
        • 1970-01-01
        • 1970-01-01
        • 2016-07-14
        • 2012-06-11
        • 2011-04-27
        • 2011-09-11
        相关资源
        最近更新 更多