6

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?

rmi
  • 532
  • 4
  • 15
feelfree
  • 11,175
  • 20
  • 96
  • 167
  • 2
    That is no duplicate because it doesn't answer the question what to do with exceptions. There's just one answer saying "beware of exceptions" without any solution provided. – Lundin Apr 23 '14 at 10:49
  • 4
    @Lundin, I don't think there is a universal solution here. The possible ones would be to rewrite the code without using exceptions at all, or to make wrappers in such a way that the exceptions do not leave the library's own code, I suppose? – SingerOfTheFall Apr 23 '14 at 10:52
  • @SingerOfTheFall I don't know either, I would probably hack up some wrapper thing like that myself. But I'm curious to know if there's some recommended practice or perhaps some C++ language feature that is useful. And since that other question wasn't helpful in providing answers for that, please don't close this one. – Lundin Apr 23 '14 at 10:57
  • I think http://stackoverflow.com/questions/199418/using-c-library-in-c-code this link will be helpful, thanks – iDebD_gh Apr 23 '14 at 11:27
  • Neither the [question](http://stackoverflow.com/questions/199418/using-c-library-in-c-code) nor the [accepted answer](http://stackoverflow.com/a/199422/1600898) mention exceptions at all. How is this a duplicate? – user4815162342 Apr 23 '14 at 12:20
  • You shouldn't allow exceptions to propagate across module boundaries anyway, even when all modules are written in C++ (cf. C++ Coding Standards #62 by Sutter & Alexandrescu. http://www.gotw.ca/publications/c++cs.htm) – Rob K Apr 23 '14 at 18:34

3 Answers3

10

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.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
4

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

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

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331