in reply to Setting $! in xs

Just assign to errno in your C code. $! is magic, so it will be automatically updated the next time it is evaluated in Perl.

But you should do that only if the error code you want to pass this way is a meaningful errno code (for example, if it is given after a system call). For all the other cases, an exception is a much saner solution.