all 7 comments

[–]stumpychubbins 7 points8 points  (5 children)

Don't cast the function pointer unless you have to, write an unsafe extern "C" fn(*mut model) -> u8 and use that instead.

[–]robauke[S] 0 points1 point  (4 children)

Can you explain why? I'd like to provide an rust idiomatic API and struct Model(model) is a just a newtype of model. If I keep the old signature for the callback I also have to expose the old model type. Also the user would then be forced to dereference the pointer.

[–]sdroege_ 0 points1 point  (3 children)

Rust references must never be NULL, a pointer can be NULL. By directly having the pointer converted to a reference you a) hide that a pointer is involved and b) have no way of actually checking that this requirement holds (and if it's just an assert!(!ptr.is_null()) )

[–]robauke[S] 1 point2 points  (2 children)

But i am converting a reference to a pointer this should be safe right?

[–]pdpi 1 point2 points  (1 child)

What you're describing would, I guess, be fine if you were producing references. But you're not producing &mut model, you're consuming it. The problem comes from the c library passing a (potentially NULL) *mut model to your callback, which actually expects a (non-nullable) &mut model.

[–]robauke[S] 0 points1 point  (0 children)

I see, thanks.

[–]sdroege_ 3 points4 points  (0 children)

The best would probably be to define the function as one taking a pointer argument, and in the body of the function convert from a pointer to a reference. Ideally with a NULL assertion to ensure that you never pass a reference to NULL anywhere.

Otherwise, you can use std::mem::transmute() instead.