about summary refs log tree commit diff
path: root/doc/tutorial/ffi.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/tutorial/ffi.md')
-rw-r--r--doc/tutorial/ffi.md209
1 files changed, 0 insertions, 209 deletions
diff --git a/doc/tutorial/ffi.md b/doc/tutorial/ffi.md
deleted file mode 100644
index 5b6d72933c9..00000000000
--- a/doc/tutorial/ffi.md
+++ /dev/null
@@ -1,209 +0,0 @@
-# Interacting with foreign code
-
-One of Rust's aims, as a system programming language, is to
-interoperate well with C code.
-
-We'll start with an example. It's a bit bigger than usual, and
-contains a number of new concepts. We'll go over it one piece at a
-time.
-
-This is a program that uses OpenSSL's `SHA1` function to compute the
-hash of its first command-line argument, which it then converts to a
-hexadecimal string and prints to standard output. If you have the
-OpenSSL libraries installed, it should 'just work'.
-
-    use std;
-    
-    native mod crypto {
-        fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8;
-    }
-    
-    fn as_hex(data: [u8]) -> str {
-        let acc = "";
-        for byte in data { acc += #fmt("%02x", byte as uint); }
-        ret acc;
-    }
-
-    fn sha1(data: str) -> str unsafe {
-        let bytes = str::bytes(data);
-        let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes),
-                                vec::len(bytes), ptr::null());
-        ret as_hex(vec::unsafe::from_buf(hash, 20u));
-    }
-    
-    fn main(args: [str]) {
-        std::io::println(sha1(args[1]));
-    }
-
-## Native modules
-
-Before we can call `SHA1`, we have to declare it. That is what this
-part of the program is responsible for:
-
-    native mod crypto {
-        fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8;
-    }
-
-A `native` module declaration tells the compiler that the program
-should be linked with a library by that name, and that the given list
-of functions are available in that library.
-
-In this case, it'll change the name `crypto` to a shared library name
-in a platform-specific way (`libcrypto.so` on Linux, for example), and
-link that in. If you want the module to have a different name from the
-actual library, you can use the `"link_name"` attribute, like:
-
-    #[link_name = "crypto"]
-    native mod something {
-        fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8;
-    }
-
-## Native calling conventions
-
-Most native C code use the cdecl calling convention, so that is what
-Rust uses by default when calling native functions. Some native functions,
-most notably the Windows API, use other calling conventions, so Rust
-provides a way to to hint to the compiler which is expected by using
-the `"abi"` attribute:
-
-    #[cfg(target_os = "win32")]
-    #[abi = "stdcall"]
-    native mod kernel32 {
-        fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;
-    }
-
-The `"abi"` attribute applies to a native mod (it can not be applied
-to a single function within a module), and must be either `"cdecl"`
-or `"stdcall"`. Other conventions may be defined in the future.
-
-## Unsafe pointers
-
-The native `SHA1` function is declared to take three arguments, and
-return a pointer.
-
-    # native mod crypto {
-    fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8;
-    # }
-
-When declaring the argument types to a foreign function, the Rust
-compiler has no way to check whether your declaration is correct, so
-you have to be careful. If you get the number or types of the
-arguments wrong, you're likely to get a segmentation fault. Or,
-probably even worse, your code will work on one platform, but break on
-another.
-
-In this case, `SHA1` is defined as taking two `unsigned char*`
-arguments and one `unsigned long`. The rust equivalents are `*u8`
-unsafe pointers and an `uint` (which, like `unsigned long`, is a
-machine-word-sized type).
-
-Unsafe pointers can be created through various functions in the
-standard lib, usually with `unsafe` somewhere in their name. You can
-dereference an unsafe pointer with `*` operator, but use
-caution—unlike Rust's other pointer types, unsafe pointers are
-completely unmanaged, so they might point at invalid memory, or be
-null pointers.
-
-## Unsafe blocks
-
-The `sha1` function is the most obscure part of the program.
-
-    # mod crypto { fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8 { out } }
-    # fn as_hex(data: [u8]) -> str { "hi" }
-    fn sha1(data: str) -> str unsafe {
-        let bytes = str::bytes(data);
-        let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes),
-                                vec::len(bytes), ptr::null());
-        ret as_hex(vec::unsafe::from_buf(hash, 20u));
-    }
-
-Firstly, what does the `unsafe` keyword at the top of the function
-mean? `unsafe` is a block modifier—it declares the block following it
-to be known to be unsafe.
-
-Some operations, like dereferencing unsafe pointers or calling
-functions that have been marked unsafe, are only allowed inside unsafe
-blocks. With the `unsafe` keyword, you're telling the compiler 'I know
-what I'm doing'. The main motivation for such an annotation is that
-when you have a memory error (and you will, if you're using unsafe
-constructs), you have some idea where to look—it will most likely be
-caused by some unsafe code.
-
-Unsafe blocks isolate unsafety. Unsafe functions, on the other hand,
-advertise it to the world. An unsafe function is written like this:
-
-    unsafe fn kaboom() { "I'm harmless!"; }
-
-This function can only be called from an unsafe block or another
-unsafe function.
-
-## Pointer fiddling
-
-The standard library defines a number of helper functions for dealing
-with unsafe data, casting between types, and generally subverting
-Rust's safety mechanisms.
-
-Let's look at our `sha1` function again.
-
-    # mod crypto { fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8 { out } }
-    # fn as_hex(data: [u8]) -> str { "hi" }
-    # fn x(data: str) -> str unsafe {
-    let bytes = str::bytes(data);
-    let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes),
-                            vec::len(bytes), ptr::null());
-    ret as_hex(vec::unsafe::from_buf(hash, 20u));
-    # }
-
-The `str::bytes` function is perfectly safe, it converts a string to
-an `[u8]`. This byte array is then fed to `vec::unsafe::to_ptr`, which
-returns an unsafe pointer to its contents.
-
-This pointer will become invalid as soon as the vector it points into
-is cleaned up, so you should be very careful how you use it. In this
-case, the local variable `bytes` outlives the pointer, so we're good.
-
-Passing a null pointer as third argument to `SHA1` causes it to use a
-static buffer, and thus save us the effort of allocating memory
-ourselves. `ptr::null` is a generic function that will return an
-unsafe null pointer of the correct type (Rust generics are awesome
-like that—they can take the right form depending on the type that they
-are expected to return).
-
-Finally, `vec::unsafe::from_buf` builds up a new `[u8]` from the
-unsafe pointer that was returned by `SHA1`. SHA1 digests are always
-twenty bytes long, so we can pass `20u` for the length of the new
-vector.
-
-## Passing structures
-
-C functions often take pointers to structs as arguments. Since Rust
-records are binary-compatible with C structs, Rust programs can call
-such functions directly.
-
-This program uses the Posix function `gettimeofday` to get a
-microsecond-resolution timer.
-
-    use std;
-    type timeval = {mutable tv_sec: u32,
-                    mutable tv_usec: u32};
-    #[nolink]
-    native mod libc {
-        fn gettimeofday(tv: *timeval, tz: *()) -> i32;
-    }
-    fn unix_time_in_microseconds() -> u64 unsafe {
-        let x = {mutable tv_sec: 0u32, mutable tv_usec: 0u32};
-        libc::gettimeofday(ptr::addr_of(x), ptr::null());
-        ret (x.tv_sec as u64) * 1000_000_u64 + (x.tv_usec as u64);
-    }
-
-The `#[nolink]` attribute indicates that there's no native library to link
-in. The standard C library is already linked with Rust programs.
-
-A `timeval`, in C, is a struct with two 32-bit integers. Thus, we
-define a record type with the same contents, and declare
-`gettimeofday` to take a pointer to such a record.
-
-The second argument to `gettimeofday` (the time zone) is not used by
-this program, so it simply declares it to be a pointer to the nil
-type. Since null pointer look the same, no matter which type they are
-supposed to point at, this is safe.