Oh yeah ive already seen that. Lots of casting to get them to compile. There are also a few external functions (glib maybe?) that take 'char *' parameters but are being fed with string literals "..." in the GNC code so i hope those functions internally are treating those params as "const char *"
On Fri, Feb 6, 2026, 7:44 AM Stefan Koch <[email protected]> wrote: > > One more thing to keep in mind for the c to c++ conversion... The c++ > compiler is stricter on some type checking. You will have to make real > code changes to allow it to compile some c code. Those changes are not > significant, but do have to be correct and verified. At least that is what > happened when I did this for some test driver source files. > > Stefan > > On Fri, Feb 6, 2026 at 9:28 AM <[email protected]> wrote: > >> John, thank you for your detailed reply. >> I've responded inline below >> If you are still unconvinced please say so and I'll abandon this. >> Thanks again. >> - russ >> >> > -----Original Message----- >> > From: John Ralls <[email protected]> >> > Sent: Thursday, February 5, 2026 9:04 PM >> > To: [email protected] >> > Cc: [email protected] >> > Subject: Re: exception fencing >> > >> > >> > >> > > On Feb 5, 2026, at 3:03 PM, <[email protected]> >> > <[email protected]> wrote: >> > > >> > > Since this is my first attempt to submit code to the GNC project I >> > > thought I’d pass my approach through the established developers first. >> > > I am interested in converting GNC code from C to C++ which will occur >> over >> > time so that the review quanta is not too overwhelming. >> > > I plan to convert build targets to only use the C++ compiler over >> time. >> > > Anything that is exposed with C linkage I plan to carry forward >> expecting at >> > some point all the callers will be C++ as well and most if not all of >> the C- >> > linkage requirements will go away. >> > > Any C++ code that is called from C-code will need a mechanism to >> prevent >> > C++ exceptions from bleeding back. >> > > I’ve developed a header file except-fence.hpp that provides the >> required >> > fencing. >> > > My first patch will be just this header file and the associated test >> files, so no >> > GNC code will be affected initially. >> > > I wanted to make the footprint small since I expect the fences will >> eventually >> > be removed. >> > > My approach is to replace the definition if the C-API functions with a >> > > macro that defines a stub C-API (extern “C”) Which instantiates an >> > ExceptFence object and uses the “forward_to” method call a local static >> > function with the original body. >> > > For Example: >> > > const char * >> > > func1(int a, gpointer b) // defined as extern “C” in header file { … } >> > > Becomes: >> > > SAFE_C_API_ARGS(const char *, func1, (int a, gpointer b), (a, b)) { … >> > > } Which (essentially) expands to: >> > > static const char *loc_func1(int a, gpointer b); extern “C” const >> > > char *func1(int a, gpointer b) { >> > > ExceptFence exf; >> > > return exf.forward_to(loc_func1, a, b); } static const char >> > > *loc_func1 (int a, gpointer b) { … } >> > > The essence of forward_to is the following: >> > > template<typename Func, typename... Args> >> > > auto forward_to(Func&& func, Args&&... args) >> > > { >> > > try { >> > > m_except_data.exception_hit = true; >> > > auto result = func(std::forward<Args>(args)...); >> > > m_except_data.exception_hit = false; >> > > return result; >> > > } >> > > catch (const std::exception& ex) { >> > > m_except_data.exception_type = &typeid(ex); >> > > m_except_data.exception_message = ex.what(); >> > > } >> > > using ReturnType = std::invoke_result_t<Func, Args...>; >> > > if constexpr (std::is_integral_v<ReturnType>) { >> > > return >> static_cast<ReturnType>(m_exception_error_integer); >> > > } else if constexpr (std::is_pointer_v<ReturnType>) { >> > > return static_cast<ReturnType>(nullptr); >> > > } else { >> > > return ReturnType{}; >> > > } >> > > } >> > > This definition of forward_to() supports functions that return >> integer types, >> > pointer types, and structure types. >> > > That appears to support most of what we need that I’ve seen. >> > > There are 4 different SAFE_C_API macros to support all the >> combinations of >> > void args and void return types. >> > > Anyway, if there are concerns about this approach, or request for >> more >> > details please let me know. >> > > Thanks for your attention and support. >> > >> > Getting rid of C entirely requires changing the GUI framework; the >> minimum >> > effort would be gtkmm but even that will be a lot of work. It isn’t >> going to >> > happen any time soon. >> >> [russ] I figured there might be some elements that are impractical to >> convert >> But I still think it makes sense to enable C++ coding in the main. There >> are just a lot >> A nice features of C++ that would be good to take advantage of. >> >> > Also to consider is that exceptions either can’t be >> > allowed to leak through the Python and Scheme bindings or those bindings >> > need to acquire exception converters. >> >> [russ] Yeah I thought that the binding interfaces would need to remain as >> C-Linkage but can still be C++ code underneath. >> >> > >> > Just switching to compiling C code with a C++ compiler doesn’t introduce >> > exceptions so the need to wrap calls in try/catch is limited to cases >> when the >> > function is reimplemented to use some C++ thing that throws. >> >> [russ] right but the code will be available for use of C++ constructs by >> developers but still callable from C compilation units >> >> > Note that >> > loc_func1 still has to check ext.m_except_data.exception_hit and if >> it’s true do >> > something with the rest. I suspect that that something will turn out to >> be >> > sufficiently not generic that having the template won’t really save >> much over >> > just catching the exception in the implementation function or writing a >> C >> > wrapper that handles exceptions in a way that’s appropriate for the >> execution >> > context at hand. >> >> [russ] I'm not sure I agree completely. The fence is only for catching >> unhandled exceptions (coding bugs), and the fence is in func1(), but the >> implementation logic is in loc_func1(). Even carefully designed C++ can >> have unusual circumstance that result in an unexpected exception. If there >> is any cleanup that needs to be done (beyond returning some error value), >> that will need to be done with a try/catch in loc_func1(). For functions >> that generate a lot of side effects and have complicated unwind logic its >> likely they won't be able to do that with a giant catch-all at the top >> anyway and need layers of try/catch to properly deal with them. I agree >> that if we mandate a giant catch-all at the top of all the C-APIs when >> implementing that might work for catching everything but in my experience >> its tricky to get right and error prone. E.g. if we instantiate an object >> before the try, those constructors can throw unprotected. >> >> > >> > BTW, “m_exception_error_integer” is a problem because it implies that >> that’s >> > a single value used for all cases and it’s not hard at all to think of >> cases where >> > different values would be needed for signaling an error. >> >> [russ] in the implementation of ExceptFence, the constructor can take any >> integer value and use that as the error value for integer return types. But >> you are right that the macros don't currently support that, but that would >> be easy to change. From what I've seen so far the return types for these >> APIs in the code base are either some kind of integer, some kind of >> pointer, or some kind of structure. The class currently supports specifying >> what the integer error value is for uncaught exceptions, but for the other >> return types it currently only supports nullptr/zeroed-out-structure, but >> that also could be fixed to support any error value of those types. >> >> So the exception fence really just ensures that uncaught exceptions >> return a known error type and that the implementation function does not >> need a v. carefully designed giant catch-all at the top. >> >> Void functions are tougher. Caught exceptions currently just return and >> leave an unknown state behind without any side effects. If there was some >> notification possible that would be nice. >> >> Once nice thing of having the fencing in a single class is if you suspect >> an unhandled exception e.g. in a void C-API func, it’s a single breakpoint >> in the code. >> >> >> >> > >> > Regards, >> > John Ralls >> >> >> _______________________________________________ >> gnucash-devel mailing list >> [email protected] >> https://lists.gnucash.org/mailman/listinfo/gnucash-devel >> >
_______________________________________________ gnucash-devel mailing list [email protected] https://lists.gnucash.org/mailman/listinfo/gnucash-devel
