feelfree
feelfree

Reputation: 11753

C++ exception handling in C codes

When we write a program in C, it is possible that we will call some libraries that were wrote in C++ but had a C interface. Then it may happen that when we call these libraries, a C++ exception will occur. So my question is how we can handle this situation. I am more interested in this problem from a C++ developer's perspective. Suppose I am developing a C++ library that will be invoked by a C program, should I stop using exception and instead return error codes? Another situation is that if I have already a fully developed C++ library that uses exception, how can I transfer this library in a quick way that will only use error returning method?

Upvotes: 6

Views: 570

Answers (3)

user4815162342
user4815162342

Reputation: 154836

You have to catch all exceptions on the C++ side and convert them to appropriate error returns in C, which may include specific error codes where appropriate. This doesn't mean that you stop using exceptions — you can still use them in C++ — but you can't expose them to C, they become an implementation detail.

A typical wrapper can be structured as follows:

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

In this simple example, the caller of thingy_get_name can detect that an error occurred, but cannot find out the details of the error. A more realistic example would catch specific exceptions, and set a last_error variable to an error code or message before returning NULL. ... would only be caught as a last resort, and would set last_error to a generic UNKNOWN_ERROR value. A separate API for querying the last error, such as thingy_last_error(), would be available for the more careful callers of thingy_get_name().

The separation between error and non-error results enables code that doesn't care about the cause of errors to simply check if it received NULL, while allowing more conscientious code to properly propagate or report the error. If your library is multi-threaded, make sure that last_error uses thread-local storage.

Upvotes: 10

David Heffernan
David Heffernan

Reputation: 612794

Then it may happen that when we call these libraries, a C++ exception will occur. So my question is how we can handle this situation.

The C code cannot handle this situation. C code cannot deal with C++ exceptions.

Suppose I am developing a C++ library that will be invoked by a C program, should I stop using exception and instead return error codes?

No. If you want the C++ library to be consumed by C++ code you should use native C++ error handling. Which means exceptions.

However, the interface that you expose to the C code must not throw exceptions. Typically this means writing an adaptor layer that catches exceptions raised by the C++ library, and converts them into error codes to be consumed by the C code.

Another situation is that if I have already a fully developed C++ library that uses exception, how can I transfer this library in a quick way that will only use error returning method?

There's really no shortcut here. You have to write the adaptor that converts C++ exceptions into C error codes. You'll be writing an adaptor anyway if you want the library to expose interfaces for both C and C++ consumers. So the aspect of error handling is just another thing to take care of with this adaptor.

Upvotes: 4

Rahul Tripathi
Rahul Tripathi

Reputation: 172378

Exception are not caught in C so if you want to catch them then in your C code or your C++ code you have to write the wrappers very carefully.

Also make sure that in your C++ functions you have your functions declared as:

extern "C"

You may also check How to mix C and C++

Upvotes: 1

Related Questions