@@ -575,16 +575,69 @@ against `libc` and `libm` by default.
575
575
576
576
# The "nullable pointer optimization"
577
577
578
- Certain types are defined to not be NULL. This includes references (` &T ` ,
579
- ` &mut T ` ), boxes (` Box<T> ` ), and function pointers (` extern "abi" fn() ` ).
580
- When interfacing with C, pointers that might be NULL are often used.
581
- As a special case, a generic ` enum ` that contains exactly two variants, one of
582
- which contains no data and the other containing a single field, is eligible
583
- for the "nullable pointer optimization". When such an enum is instantiated
584
- with one of the non-nullable types, it is represented as a single pointer,
585
- and the non-data variant is represented as the NULL pointer. So
586
- ` Option<extern "C" fn(c_int) -> c_int> ` is how one represents a nullable
587
- function pointer using the C ABI.
578
+ Certain Rust types are defined to never be ` null ` . This includes references (` &T ` ,
579
+ ` &mut T ` ), boxes (` Box<T> ` ), and function pointers (` extern "abi" fn() ` ). When
580
+ interfacing with C, pointers that might be ` null ` are often used, which would seem to
581
+ require some messy ` transmute ` s and/or unsafe code to handle conversions to/from Rust types.
582
+ However, the language provides a workaround.
583
+
584
+ As a special case, an ` enum ` is eligible for the "nullable pointer optimization" if it contains
585
+ exactly two variants, one of which contains no data and the other contains a field of one of the
586
+ non-nullable types listed above. This means no extra space is required for a discriminant; rather,
587
+ the empty variant is represented by putting a ` null ` value into the non-nullable field. This is
588
+ called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible
589
+ types.
590
+
591
+ The most common type that takes advantage of the nullable pointer optimization is ` Option<T> ` ,
592
+ where ` None ` corresponds to ` null ` . So ` Option<extern "C" fn(c_int) -> c_int> ` is a correct way
593
+ to represent a nullable function pointer using the C ABI (corresponding to the C type
594
+ ` int (*)(int) ` ).
595
+
596
+ Here is a contrived example. Let's say some C library has a facility for registering a
597
+ callback, which gets called in certain situations. The callback is passed a function pointer
598
+ and an integer and it is supposed to run the function with the integer as a parameter. So
599
+ we have function pointers flying across the FFI boundary in both directions.
600
+
601
+ ``` rust
602
+ # #![feature(libc)]
603
+ extern crate libc;
604
+ use libc :: c_int;
605
+
606
+ # #[cfg(hidden)]
607
+ extern " C" {
608
+ /// Register the callback.
609
+ fn register (cb : Option <extern "C " fn (Option <extern "C " fn (c_int ) -> c_int >, c_int ) -> c_int >);
610
+ }
611
+ # unsafe fn register (_ : Option <extern "C " fn (Option <extern "C " fn (c_int ) -> c_int >,
612
+ # c_int ) -> c_int >)
613
+ # {}
614
+
615
+ /// This fairly useless function receives a function pointer and an integer
616
+ /// from C, and returns the result of calling the function with the integer.
617
+ /// In case no function is provided, it squares the integer by default.
618
+ extern " C" fn apply (process : Option <extern "C " fn (c_int ) -> c_int >, int : c_int ) -> c_int {
619
+ match process {
620
+ Some (f ) => f (int ),
621
+ None => int * int
622
+ }
623
+ }
624
+
625
+ fn main () {
626
+ unsafe {
627
+ register (Some (apply ));
628
+ }
629
+ }
630
+ ```
631
+
632
+ And the code on the C side looks like this:
633
+
634
+ ``` c
635
+ void register (void (* f)(void (* )(int), int)) {
636
+ ...
637
+ }
638
+ ```
639
+
640
+ No `transmute` required!
588
641
589
642
# Calling Rust code from C
590
643
0 commit comments