Not necessarily.
For the setjmp variant, I’m suggesting that you’d have a wrapper like
fn with_setjmp<R>(impl FnOnce() -> R) -> Option<R>
which in turn would use a function defined in C like
int with_setjmp_c(void (*callback)(void *ctx), void *ctx);
which would call setjmp then call the provided callback, which would be written in Rust.
And then the error handler that calls longjmp could be written in either C or Rust, doesn’t matter. So it would be Rust -> C (with_setjmp_c) -> Rust -> C (libjpeg APIs) -> Rust/C (error handler) -> longjmp, unwinding to with_setjmp_c.
For the C++ variant, you would have to avoid Rust code in the middle because that would trigger the unwinding abort, but you would wrap individual libjpeg APIs in C++ and also define the error handler in C++, so it would be Rust -> C++ (wrapper) -> C -> C++ (error handler), unwinding to the wrapper.