A number of cases were not handled properly: even though optional
userdata was allowed, the handling would cause unreachable to be
reached if null handles were actually passed. Also, being able to use
void to specify "no userdata please" is useful; however, in this case
we do have to still pass NULL to the C library calls.
The casting logic has been pulled out to some helper functions, which
make it more consistent. Some mediocre additional test coverage has
been added as well.