@@ -461,12 +461,11 @@ global state. In order to access these variables, you declare them in `extern`
461
461
blocks with the ` static ` keyword:
462
462
463
463
``` rust,no_run
464
- # #![feature(libc)]
465
- extern crate libc;
464
+ use std::os::raw::c_int;
466
465
467
466
#[link(name = "readline")]
468
467
extern {
469
- static rl_readline_version: libc:: c_int;
468
+ static rl_readline_version: c_int;
470
469
}
471
470
472
471
fn main() {
@@ -480,15 +479,14 @@ interface. To do this, statics can be declared with `mut` so we can mutate
480
479
them.
481
480
482
481
``` rust,no_run
483
- # #![feature(libc)]
484
- extern crate libc;
485
482
486
483
use std::ffi::CString;
484
+ use std::os::raw::c_char;
487
485
use std::ptr;
488
486
489
487
#[link(name = "readline")]
490
488
extern {
491
- static mut rl_prompt: *const libc:: c_char;
489
+ static mut rl_prompt: *const c_char;
492
490
}
493
491
494
492
fn main() {
@@ -513,14 +511,13 @@ calling foreign functions. Some foreign functions, most notably the Windows API,
513
511
conventions. Rust provides a way to tell the compiler which convention to use:
514
512
515
513
``` rust
516
- # #![feature(libc)]
517
- extern crate libc;
514
+ use std :: os :: raw :: c_int;
518
515
519
516
#[cfg(all(target_os = " win32" , target_arch = " x86" ))]
520
517
#[link(name = " kernel32" )]
521
518
#[allow(non_snake_case)]
522
519
extern " stdcall" {
523
- fn SetEnvironmentVariableA (n : * const u8 , v : * const u8 ) -> libc :: c_int ;
520
+ fn SetEnvironmentVariableA (n : * const u8 , v : * const u8 ) -> c_int ;
524
521
}
525
522
# fn main () { }
526
523
```
@@ -575,16 +572,45 @@ against `libc` and `libm` by default.
575
572
576
573
# The "nullable pointer optimization"
577
574
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
575
+ Certain Rust types are defined to never be ` null ` . This includes references (` &T ` ,
576
+ ` &mut T ` ), boxes (` Box<T> ` ), and function pointers (` extern "abi" fn() ` ). When
577
+ interfacing with C, pointers that might be ` null ` are often used, which would seem to
578
+ require some messy ` transmute ` s and/or unsafe code to handle conversions to/from Rust types.
579
+ However, the language provides a workaround.
580
+
581
+ As a special case, an ` enum ` that contains exactly two variants, one of
582
582
which contains no data and the other containing a single field, is eligible
583
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.
584
+ with one of the non-nullable types listed above, it is represented as a single pointer,
585
+ and the non-data variant is represented as the null pointer. This is called an
586
+ "optimization", but unlike other optimizations it is guaranteed to apply to
587
+ eligible types.
588
+
589
+ The most common type that takes advantage of the nullable pointer optimization is ` Option<T> ` ,
590
+ where ` None ` corresponds to ` null ` . So ` Option<extern "C" fn(c_int) -> c_int> ` is a correct way
591
+ to represent a nullable function pointer using the C ABI (corresponding to the C type
592
+ ` int (*)(int) ` ). (However, generics are not required to get the optimization. A simple
593
+ ` enum NullableIntRef { Int(Box<i32>), NotInt } ` is also represented as a single pointer.)
594
+
595
+ Here is an example:
596
+
597
+ ``` rust
598
+ use std :: os :: raw :: c_int;
599
+
600
+ /// This fairly useless function receives a function pointer and an integer
601
+ /// from C, and returns the result of calling the function with the integer.
602
+ /// In case no function is provided, it squares the integer by default.
603
+ #[no_mangle]
604
+ pub extern fn apply (process : Option <extern "C " fn (c_int ) -> c_int >, int : c_int ) -> c_int {
605
+ match process {
606
+ Some (f ) => unsafe { f (int ) },
607
+ None => int * int
608
+ }
609
+ }
610
+ # fn main () {}
611
+ ```
612
+
613
+ No ` tranmsute ` required!
588
614
589
615
# Calling Rust code from C
590
616
@@ -642,12 +668,11 @@ void bar(void *arg);
642
668
We can represent this in Rust with the `c_void` type:
643
669
644
670
```rust
645
- # #![feature(libc)]
646
- extern crate libc;
671
+ use std::os::raw::c_void;
647
672
648
673
extern "C" {
649
- pub fn foo(arg: *mut libc:: c_void);
650
- pub fn bar(arg: *mut libc:: c_void);
674
+ pub fn foo(arg: *mut c_void);
675
+ pub fn bar(arg: *mut c_void);
651
676
}
652
677
# fn main() {}
653
678
```
0 commit comments