c++cexceptionlanguage-binding

How to convert exceptions to errors and error messages when wrapping C++ classes API for C consumption?


The problem

Say you've got a C++ class.

Say you want to export its constructor(s) and methods to C.

Say you followed the advices given in the solution to the "Wrapping C++ class API for C consumption" question.

Now say your class constructor can throw one or more exceptions, which you want to catch on the C++ side before returning to the C world, whilst still giving the C user the chance to get information about the error that just happened.

First approach

I could check that MyClass_new() returned a NULL pointer and then retrieve the "last error message" occurred in the library with a function, but when the constructor fails there's just no object to provide the right context for the error retrieval, therefore a global variable should be used to hold the last error which however undermines the reentrancy of the library.

Second approach

Another possibility I can think of, which is actually the solution I came up with, is for the class to trap the exception inside the constructor itself, convert it to an error message and put the object into a "error state" of sort.

After each

MyClass myObj = MyClass_new();

the following check would be performed

if (MyClass_isInErrorState(myObj))

and the error message would be retrieved with the next statement

const char *error = MyClass_getLastError(myObj);

Third approach

Another possibility I can think of is to pass a pointer to a buffer of a given size to each function that can fail, which would be filled up with the error message, but it looks messy.

How would you do it? Is there a de facto standard way of dealing with such issues?


Solution

  • Replying to my own question.

    I think I will go with a slightly modified second approach.

    The constructor will return BOOL like all the other functions that can fail and will accept a MyClass * out parameter which will be set to some meaningful value even in case of error, so that MyClass_getLastError(myObj) could be used.

    This gets rid of the extra MyClass_isInErrorState() function.

    MyClass on the C side will be an opaque pointer and on the C++ side will be a pointer to a structure holding a pointer, possibly NULL, to the class' object and a buffer of sorts that contains the error string.