One of my OCaml projects employs some C stub code which applies OCaml callbacks previously registered with Callback.register
, using the caml_callback_exn
function. If an OCaml callback raises an exception this is detected by applying the Is_exception_result
macro to the return value of caml_callback_exn
and the exception object is obtained using the Extract_exception
macro. The program does not necessarily terminate or reraise in view of such an exception: instead the issue is logged, making use of the caml_format_exception
function to provide a textual representation of the exception object, and in some cases then allowed to continue without reraising - in particular where the code is executing in an event loop and there is no OCaml code which can sensibly catch the exception further down the stack if it were to be reraised.
I am aware of the problems with caml_callback_exn
(which are dealt with in the manner recommended in the manual), and although the code is correct I have been considering moving to OCaml-5.3’s new caml_callback_res
function, which returns a caml_result
type. However I have not managed to work out how to obtain the exception object from its return value in order to apply caml_format_exception
to log it.
According to the documentation, the public API for the caml_result
type comprises the Result_value
and Result_exception
macros to construct caml_result
objects, and the caml_result_is_exception
and caml_get_value_or_raise
functions to consume them. In the case of an exception the C exception object in fact resides in the ‘data’ field of the caml_result_private
C struct, but as the name suggests that struct’s fields are not part of the public API. The caml_get_value_or_raise
function is available, but if the caml_result_is_exception
function returns true then it always reraises, which is not what I want.
Does anyone know if there is any way around this without using non-public API?