Skip to content

Commit

Permalink
doc: Un-ignore lots of guide-ffi tests
Browse files Browse the repository at this point in the history
Using some strategically-placed `#` markers most of the examples are testable
(and their contents are nontrivial).

Closes #13445
  • Loading branch information
alexcrichton committed Apr 12, 2014
1 parent ecc774f commit f862e12
Showing 1 changed file with 58 additions and 23 deletions.
81 changes: 58 additions & 23 deletions src/doc/guide-ffi.md
Expand Up @@ -11,14 +11,16 @@ snappy includes a C interface (documented in
The following is a minimal example of calling a foreign function which will
compile if snappy is installed:

~~~~ {.ignore}
~~~~
extern crate libc;
use libc::size_t;
#[link(name = "snappy")]
# #[cfg(ignore_this)]
extern {
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
}
# unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a }
fn main() {
let x = unsafe { snappy_max_compressed_length(100) };
Expand Down Expand Up @@ -78,7 +80,11 @@ vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous
length is number of elements currently contained, and the capacity is the total size in elements of
the allocated memory. The length is less than or equal to the capacity.

~~~~ {.ignore}
~~~~
# extern crate libc;
# use libc::{c_int, size_t};
# unsafe fn snappy_validate_compressed_buffer(_: *u8, _: size_t) -> c_int { 0 }
# fn main() {}
pub fn validate_compressed_buffer(src: &[u8]) -> bool {
unsafe {
snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0
Expand All @@ -98,14 +104,20 @@ required capacity to hold the compressed output. The vector can then be passed t
`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
the true length after compression for setting the length.

~~~~ {.ignore}
pub fn compress(src: &[u8]) -> ~[u8] {
~~~~
# extern crate libc;
# use libc::{size_t, c_int};
# unsafe fn snappy_compress(a: *u8, b: size_t, c: *mut u8,
# d: *mut size_t) -> c_int { 0 }
# unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a }
# fn main() {}
pub fn compress(src: &[u8]) -> Vec<u8> {
unsafe {
let srclen = src.len() as size_t;
let psrc = src.as_ptr();
let mut dstlen = snappy_max_compressed_length(srclen);
let mut dst = slice::with_capacity(dstlen as uint);
let mut dst = Vec::with_capacity(dstlen as uint);
let pdst = dst.as_mut_ptr();
snappy_compress(psrc, srclen, pdst, &mut dstlen);
Expand All @@ -118,16 +130,26 @@ pub fn compress(src: &[u8]) -> ~[u8] {
Decompression is similar, because snappy stores the uncompressed size as part of the compression
format and `snappy_uncompressed_length` will retrieve the exact buffer size required.

~~~~ {.ignore}
pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
~~~~
# extern crate libc;
# use libc::{size_t, c_int};
# unsafe fn snappy_uncompress(compressed: *u8,
# compressed_length: size_t,
# uncompressed: *mut u8,
# uncompressed_length: *mut size_t) -> c_int { 0 }
# unsafe fn snappy_uncompressed_length(compressed: *u8,
# compressed_length: size_t,
# result: *mut size_t) -> c_int { 0 }
# fn main() {}
pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
unsafe {
let srclen = src.len() as size_t;
let psrc = src.as_ptr();
let mut dstlen: size_t = 0;
snappy_uncompressed_length(psrc, srclen, &mut dstlen);
let mut dst = slice::with_capacity(dstlen as uint);
let mut dst = Vec::with_capacity(dstlen as uint);
let pdst = dst.as_mut_ptr();
if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
Expand Down Expand Up @@ -187,16 +209,19 @@ A basic example is:

Rust code:

~~~~ {.ignore}
~~~~
extern fn callback(a:i32) {
println!("I'm called from C with value {0}", a);
}
#[link(name = "extlib")]
# #[cfg(ignore)]
extern {
fn register_callback(cb: extern "C" fn(i32)) -> i32;
fn register_callback(cb: extern fn(i32)) -> i32;
fn trigger_callback();
}
# unsafe fn register_callback(cb: extern fn(i32)) -> i32 { 0 }
# unsafe fn trigger_callback() { }
fn main() {
unsafe {
Expand Down Expand Up @@ -240,33 +265,39 @@ referenced Rust object.

Rust code:

~~~~ {.ignore}
~~~~
struct RustObject {
a: i32,
// other members
}
extern fn callback(target: *RustObject, a:i32) {
extern fn callback(target: *mut RustObject, a:i32) {
println!("I'm called from C with value {0}", a);
(*target).a = a; // Update the value in RustObject with the value received from the callback
unsafe {
// Update the value in RustObject with the value received from the callback
(*target).a = a;
}
}
#[link(name = "extlib")]
# #[cfg(ignore)]
extern {
fn register_callback(target: *RustObject, cb: extern "C" fn(*RustObject, i32)) -> i32;
fn register_callback(target: *mut RustObject,
cb: extern fn(*mut RustObject, i32)) -> i32;
fn trigger_callback();
}
# unsafe fn register_callback(a: *mut RustObject,
# b: extern fn(*mut RustObject, i32)) -> i32 { 0 }
# unsafe fn trigger_callback() {}
fn main() {
// Create the object that will be referenced in the callback
let rust_object = ~RustObject{a: 5, ...};
let mut rust_object = ~RustObject{ a: 5 };
unsafe {
// Gets a raw pointer to the object
let target_addr:*RustObject = ptr::to_unsafe_ptr(rust_object);
register_callback(target_addr, callback);
trigger_callback(); // Triggers the callback
register_callback(&mut *rust_object, callback);
trigger_callback();
}
}
~~~~
Expand Down Expand Up @@ -403,13 +434,15 @@ Foreign APIs often export a global variable which could do something like track
global state. In order to access these variables, you declare them in `extern`
blocks with the `static` keyword:

~~~{.ignore}
~~~
extern crate libc;
#[link(name = "readline")]
# #[cfg(ignore)]
extern {
static rl_readline_version: libc::c_int;
}
# static rl_readline_version: libc::c_int = 0;
fn main() {
println!("You have readline version {} installed.",
Expand All @@ -421,21 +454,23 @@ Alternatively, you may need to alter global state provided by a foreign
interface. To do this, statics can be declared with `mut` so rust can mutate
them.

~~~{.ignore}
~~~
extern crate libc;
use std::ptr;
#[link(name = "readline")]
# #[cfg(ignore)]
extern {
static mut rl_prompt: *libc::c_char;
}
# static mut rl_prompt: *libc::c_char = 0 as *libc::c_char;
fn main() {
do "[my-awesome-shell] $".as_c_str |buf| {
"[my-awesome-shell] $".with_c_str(|buf| {
unsafe { rl_prompt = buf; }
// get a line, process it
unsafe { rl_prompt = ptr::null(); }
}
});
}
~~~

Expand Down

5 comments on commit f862e12

@bors
Copy link
Contributor

@bors bors commented on f862e12 Apr 12, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from sfackler
at alexcrichton@f862e12

@bors
Copy link
Contributor

@bors bors commented on f862e12 Apr 12, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging alexcrichton/rust/stop-ignoring-ffi = f862e12 into auto

@bors
Copy link
Contributor

@bors bors commented on f862e12 Apr 12, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alexcrichton/rust/stop-ignoring-ffi = f862e12 merged ok, testing candidate = 82cd9ac

@bors
Copy link
Contributor

@bors bors commented on f862e12 Apr 12, 2014

@bors
Copy link
Contributor

@bors bors commented on f862e12 Apr 12, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 82cd9ac

Please sign in to comment.