Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 612
feelfree Avatar asked Apr 23 '14 10:04

feelfree


People also ask

What does #error do in C?

In the C Programming Language, the #error directive causes preprocessing to stop at the location where the directive is encountered. Information following the #error directive is output as a message prior to stopping preprocessing.

Can you throw exceptions in C?

C doesn't support exceptions. You can try compiling your C code as C++ with Visual Studio or G++ and see if it'll compile as-is. Most C applications will compile as C++ without major changes, and you can then use the try... catch syntax.

Does C have try except?

The try-except statement is a Microsoft extension to the C language that enables applications to gain control of a program when events that normally terminate execution occur. Such events are called exceptions, and the mechanism that deals with exceptions is called structured exception handling.

How many types of exception handling are there in C?

There are two types of exceptions: a)Synchronous, b)Asynchronous (i.e., exceptions which are beyond the program's control, such as disc failure, keyboard interrupts etc.).


3 Answers

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.

like image 38
David Heffernan Avatar answered Oct 04 '22 12:10

David Heffernan


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.

like image 111
user4815162342 Avatar answered Oct 04 '22 10:10

user4815162342


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++

like image 31
Rahul Tripathi Avatar answered Oct 04 '22 10:10

Rahul Tripathi