From: William S F. <ws...@fu...> - 2013-11-11 20:11:48
|
On 08/11/13 15:28, Petr Petrov wrote: > VZ>> but there are also some fundamental questions here, e.g. how to > deal with the exceptions > > I thought a little about exception wrapping before. > I think that we can use return codes for exception handling in C. > Before introducing exception in C++, many C programs use return codes > for indicating an error. > So, return error "codes" is natural way for error handling in C. > > My proposition (draft) is the following. > For instance, C++ code: > > class ArrayOfInt // just for sample > { > public: > int GetValue(size_t index) throw (std::out_of_range) const; > // ... implementation > } > > int ArrayOfInt::GetValue(size_t index) is able to throw exception of > type std::out_of_range. > In C we can use the following wrapping: > > void* ArrayOfInt_GetValue(void* array_of_int, size_t index, int* result); > > and at client side you should check (or do not check and silently ignore > errors) return value: > > void * array1 = 0; > void* error_code = 0; > int value_to_get = 0; > > // create array > // array1 = ArrayOfInt_Factor(); > > error_code = ArrayOfInt_GetValue(array1, 7, &value_to_get); > if (error_code) > { > // oops! An error was caused > // In fact error_code is not plain error code such as errno_t C type, > // it is opaque pointer to exception class > }else > { > // success case > } > > Of course such approach maybe is not convenience for C developers. > More serious problem is managing exception object life-time. > Who should destroy such exception object? > Also we need to have a way to detect source type of exception and obtain > some information from it. > I am not ready to answer for this question now. Maybe later I will have > idea or > somebody else could contribute some idea. > > At least we can generate general wrapper class for all exceptions and > nest generated exception inside. > > VZ>> But I think this needs to be the first aim for any C++-in-C++ project because it > VZ>> will be needed anyhow and, personally, I'd consider writing the C++ > VZ>> wrappers by hand if the C API is available > > Note that for extreme case you do not need to have any C target language module. > You can generate wrappers for some particular target language which could be used as raw C wrapping. > For instance, I see that C# module could be used for such goal. > It produces clean C API, for instance for example above it will produce something like: > > SWIGEXPORT int SWIGSTDCALL CSharp_ModuleName_ArrayOfInt_GetValue(void * jarg1, int jarg2) { > } > > (it is not preciously, I am not expert in Swig, I am investigating it) > But I see that C# uses some callbacks for exception wrapping. > My thoughts on this are like Vadim's... this must be built on top of a C module and getting the C module working first makes sense. In essence, this problem is not much different to any of the other languages in that they nearly all build another layer on top of a flattened C API. You are correct in noticing that the C# layer is nearly what is needed, but there are some issues with it. The main problem with it is that it is completely type unsafe (uses void *) everywhere, whereas a C API should use what limited type safety the language offers. The exception handling is also no good... The C# module implementation for exceptions does not pass any parameter in the method call to retrieve exception information. It relies on the fact that thread local variables are part of C# and so a C# thread local variable is used to hold information about an exception per thread. This approach is optimised for C# because, firstly, marshalling additional parameters from C# to C in the non-exceptional case can add a very notable overhead if few (zero) parameters are being used and secondly thread local variables are always available in C#. Neither of these are true for C calling C, so the approach of adding an additional parameter for each method would be the best approach. I think you should have a look at the current C target language implementation in the gsoc2012-c branch on Github. It even has an implementation for handling exceptions, I don't know how complete it is though. It uses a structure to hold the exception information, such as type of exception and exception message. It uses longjmp/setjmp for the implementation. I'm not sure if this latter bit is the ideal approach without giving some more thought, but I think using a struct to hold exception info received via an additional parameter is good, as well as the macros to handle the exceptions. The macros handle the memory for the exceptions. Look at the exceptions example for usage: https://github.com/swig/swig/blob/gsoc2012-c/Examples/c/exception/runme.c I would advise spending some time seeing how well it works, run some simple examples and get an idea how how many C/C++ features are missing. From what I recall, template support is not good, which is odd because the template support should be handled by the core. Lastly, it would be fantastic if you could work on this as I'd like to see this merged into master as an important 'target language' for SWIG. William |