# Advice for wrapping c++ library that throws exceptions?

**URL:** <https://discourse.julialang.org/t/advice-for-wrapping-c-library-that-throws-exceptions/101855>\
**Category:** General Usage\
**Tags:** c\
**Created:** [July 20, 2023, 9:27pm UTC](https://discourse.julialang.org/t/advice-for-wrapping-c-library-that-throws-exceptions/101855 "2023-07-20T21:27:10Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)\
**Post date:** [July 20, 2023, 9:27pm UTC](https://discourse.julialang.org/t/advice-for-wrapping-c-library-that-throws-exceptions/101855/1 "2023-07-20T21:27:11Z")

</div>

I have a vendor library that throws exceptions, which makes wrapping them a bit more miserable. I only have access to headers and shared libraries, and I couldn’t figure out a way to link the libraries and prevent exceptions (it is probably impossible to prevent it).

Having the REPL abort because of an exception is not good, but wrapping the calls seems clunky (but at least it doesn’t abort). I was looking for anyone’s advice on how to handle this?

TLDR: I created a struct that had a boolean representing if the call was exception-free, and then a sequence of struct members representing the various forms of return types (crude sum type I guess) and then a `const char *` field that would contain the exception text. It sort of is okay-ish, but I would be glad to hear about anything more sleek.

> **Example C++ code**
>
> ```cpp
> #include <cmath>
> #include <exception>
> #include <iostream>
> #include <string>
> #include <string.h>
> 
> constexpr size_t N = 2048;
> 
> extern "C" {
> 
> //------------------//
> // notional library //
> //------------------//
> typedef struct Result {
> bool success;
> int as_int;
> double as_double;
> char what[N];
> } Result;
> 
> double my_sqrt(double f) {
> if (f < 0.0)
> throw std::domain_error("negative value");
> return sqrt(f);
> }
> 
> int add1(int f) {
> return f + 1;
> }
> 
> //----------------------//
> // notional wrapper API //
> //----------------------//
> Result my_sqrt_wrapper(double f) {
> Result ret;
> 
> try {
> ret.as_double = my_sqrt(f);
> ret.success = true;
> } catch (const std::exception& e) {
> ret.success = false;
> strncpy(ret.what, e.what(), N);
> ret.what[N] = '\0';
> }
> 
> return ret;
> }
> 
> Result add1_wrapper(int f) {
> Result ret;
> 
> try {
> ret.as_int = add1(f);
> ret.success = true;
> } catch (const std::exception& e) {
> ret.success = false;
> strncpy(ret.what, e.what(), N);
> ret.what[N] = '\0';
> }
> 
> return ret;
> }
> 
> ```

> **Example Julia Wrapper**
>
> ```julia
> struct Result
> success::Cuchar
> as_int::Cint
> as_double::Cdouble
> what::NTuple{2048, Cchar}
> end
> 
> function my_sqrt(x)
> a = @ccall "./libstuff.so".my_sqrt_wrapper(x::Cdouble)::Result
> if iszero(a.success)
> string_end = findfirst(iszero, a.what) - 1
> message = join(convert.(Char, a.what[1:string_end]))
> throw(DomainError(x, message))
> else
> a.as_double
> end
> end
> 
> function add1(x)
> a = @ccall "./libstuff.so".add1_wrapper(x::Cint)::Result
> if iszero(a.success)
> string_end = findfirst(iszero, a.what) - 1
> message = join(convert.(Char, a.what[1:string_end]))
> throw(DomainError(x, message))
> else
> a.as_int
> end
> end
> 
> @show add1(3)
> @show my_sqrt(4)
> @show my_sqrt(-4)
> 
> ```
