# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The Rust Project Developers # This file is distributed under the same license as the Rust package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Rust 0.8\n" "POT-Creation-Date: 2013-08-10 07:44+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Plain text #: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4 #: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4 #: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4 msgid "# Introduction" msgstr "" #. type: Plain text #: doc/tutorial.md:868 doc/tutorial-ffi.md:143 msgid "# Destructors" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:2 msgid "% Rust Foreign Function Interface Tutorial" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:10 msgid "" "This tutorial will use the [snappy](https://code.google.com/p/snappy/) " "compression/decompression library as an introduction to writing bindings for " "foreign code. Rust is currently unable to call directly into a C++ library, " "but snappy includes a C interface (documented in [`snappy-c.h`](https://code." "google.com/p/snappy/source/browse/trunk/snappy-c.h))." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:13 msgid "" "The following is a minimal example of calling a foreign function which will " "compile if snappy is installed:" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:16 msgid "~~~~ {.xfail-test} use std::libc::size_t;" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:21 #, no-wrap msgid "" "#[link_args = \"-lsnappy\"]\n" "extern {\n" " fn snappy_max_compressed_length(source_length: size_t) -> size_t;\n" "}\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:27 #, no-wrap msgid "" "fn main() {\n" " let x = unsafe { snappy_max_compressed_length(100) };\n" " println(fmt!(\"max compressed length of a 100 byte buffer: %?\", x));\n" "}\n" "~~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:31 msgid "" "The `extern` block is a list of function signatures in a foreign library, in " "this case with the platform's C ABI. The `#[link_args]` attribute is used to " "instruct the linker to link against the snappy library so the symbols are " "resolved." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:37 msgid "" "Foreign functions are assumed to be unsafe so calls to them need to be " "wrapped with `unsafe {}` as a promise to the compiler that everything " "contained within truly is safe. C libraries often expose interfaces that " "aren't thread-safe, and almost any function that takes a pointer argument " "isn't valid for all possible inputs since the pointer could be dangling, and " "raw pointers fall outside of Rust's safe memory model." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:41 msgid "" "When declaring the argument types to a foreign function, the Rust compiler " "will not check if the declaration is correct, so specifying it correctly is " "part of keeping the binding correct at runtime." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:43 msgid "The `extern` block can be extended to cover the entire snappy API:" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:46 msgid "~~~~ {.xfail-test} use std::libc::{c_int, size_t};" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:65 #, no-wrap msgid "" "#[link_args = \"-lsnappy\"]\n" "extern {\n" " fn snappy_compress(input: *u8,\n" " input_length: size_t,\n" " compressed: *mut u8,\n" " compressed_length: *mut size_t) -> c_int;\n" " fn snappy_uncompress(compressed: *u8,\n" " compressed_length: size_t,\n" " uncompressed: *mut u8,\n" " uncompressed_length: *mut size_t) -> c_int;\n" " fn snappy_max_compressed_length(source_length: size_t) -> size_t;\n" " fn snappy_uncompressed_length(compressed: *u8,\n" " compressed_length: size_t,\n" " result: *mut size_t) -> c_int;\n" " fn snappy_validate_compressed_buffer(compressed: *u8,\n" " compressed_length: size_t) -> c_int;\n" "}\n" "~~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:67 msgid "# Creating a safe interface" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:71 msgid "" "The raw C API needs to be wrapped to provide memory safety and make use of " "higher-level concepts like vectors. A library can choose to expose only the " "safe, high-level interface and hide the unsafe internal details." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:76 msgid "" "Wrapping the functions which expect buffers involves using the `vec::raw` " "module to manipulate Rust vectors as pointers to memory. Rust's vectors are " "guaranteed to be a contiguous block of memory. The 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." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:84 #, no-wrap msgid "" "~~~~ {.xfail-test}\n" "pub fn validate_compressed_buffer(src: &[u8]) -> bool {\n" " unsafe {\n" " snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0\n" " }\n" "}\n" "~~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:88 msgid "" "The `validate_compressed_buffer` wrapper above makes use of an `unsafe` " "block, but it makes the guarantee that calling it is safe for all inputs by " "leaving off `unsafe` from the function signature." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:91 msgid "" "The `snappy_compress` and `snappy_uncompress` functions are more complex, " "since a buffer has to be allocated to hold the output too." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:96 msgid "" "The `snappy_max_compressed_length` function can be used to allocate a vector " "with the maximum required capacity to hold the compressed output. The vector " "can then be passed to the `snappy_compress` function as an output parameter. " "An output parameter is also passed to retrieve the true length after " "compression for setting the length." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:102 #, no-wrap msgid "" "~~~~ {.xfail-test}\n" "pub fn compress(src: &[u8]) -> ~[u8] {\n" " unsafe {\n" " let srclen = src.len() as size_t;\n" " let psrc = src.as_ptr();\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:106 #, no-wrap msgid "" " let mut dstlen = snappy_max_compressed_length(srclen);\n" " let mut dst = vec::with_capacity(dstlen as uint);\n" " let pdst = dst.as_mut_ptr();\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:113 #, no-wrap msgid "" " snappy_compress(psrc, srclen, pdst, &mut dstlen);\n" " dst.set_len(dstlen as uint);\n" " dst\n" " }\n" "}\n" "~~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:116 msgid "" "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." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:122 #, no-wrap msgid "" "~~~~ {.xfail-test}\n" "pub fn uncompress(src: &[u8]) -> Option<~[u8]> {\n" " unsafe {\n" " let srclen = src.len() as size_t;\n" " let psrc = src.as_ptr();\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:125 #, no-wrap msgid "" " let mut dstlen: size_t = 0;\n" " snappy_uncompressed_length(psrc, srclen, &mut dstlen);\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:128 #, no-wrap msgid "" " let mut dst = vec::with_capacity(dstlen as uint);\n" " let pdst = dst.as_mut_ptr();\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:138 #, no-wrap msgid "" " if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {\n" " dst.set_len(dstlen as uint);\n" " Some(dst)\n" " } else {\n" " None // SNAPPY_INVALID_INPUT\n" " }\n" " }\n" "}\n" "~~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:141 msgid "" "For reference, the examples used here are also available as an [library on " "GitHub](https://github.com/thestinger/rust-snappy)." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:147 msgid "" "Foreign libraries often hand off ownership of resources to the calling code, " "which should be wrapped in a destructor to provide safety and guarantee " "their release." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:150 msgid "" "A type with the same functionality as owned boxes can be implemented by " "wrapping `malloc` and `free`:" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:156 msgid "" "~~~~ use std::cast; use std::libc::{c_void, size_t, malloc, free}; use std::" "ptr; use std::unstable::intrinsics;" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:161 #, no-wrap msgid "" "// a wrapper around the handle returned by the foreign code\n" "pub struct Unique {\n" " priv ptr: *mut T\n" "}\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:172 #, no-wrap msgid "" "impl Unique {\n" " pub fn new(value: T) -> Unique {\n" " unsafe {\n" " let ptr = malloc(std::mem::size_of::() as size_t) as *mut T;\n" " assert!(!ptr::is_null(ptr));\n" " // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it\n" " intrinsics::move_val_init(&mut *ptr, value);\n" " Unique{ptr: ptr}\n" " }\n" " }\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:177 #, no-wrap msgid "" " // the 'r lifetime results in the same semantics as `&*x` with ~T\n" " pub fn borrow<'r>(&'r self) -> &'r T {\n" " unsafe { cast::copy_lifetime(self, &*self.ptr) }\n" " }\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:183 #, no-wrap msgid "" " // the 'r lifetime results in the same semantics as `&mut *x` with ~T\n" " pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {\n" " unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) }\n" " }\n" "}\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:195 #, no-wrap msgid "" "#[unsafe_destructor]\n" "impl Drop for Unique {\n" " fn drop(&self) {\n" " unsafe {\n" " let x = intrinsics::init(); // dummy value to swap in\n" " // moving the object out is needed to call the destructor\n" " ptr::replace_ptr(self.ptr, x);\n" " free(self.ptr as *c_void)\n" " }\n" " }\n" "}\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:202 #, no-wrap msgid "" "// A comparison between the built-in ~ and this reimplementation\n" "fn main() {\n" " {\n" " let mut x = ~5;\n" " *x = 10;\n" " } // `x` is freed here\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:209 #, no-wrap msgid "" " {\n" " let mut y = Unique::new(5);\n" " *y.borrow_mut() = 10;\n" " } // `y` is freed here\n" "}\n" "~~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:211 msgid "# Linking" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:215 msgid "" "In addition to the `#[link_args]` attribute for explicitly passing arguments " "to the linker, an `extern mod` block will pass `-lmodname` to the linker by " "default unless it has a `#[nolink]` attribute applied." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:217 msgid "# Unsafe blocks" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:221 msgid "" "Some operations, like dereferencing unsafe pointers or calling functions " "that have been marked unsafe are only allowed inside unsafe blocks. Unsafe " "blocks isolate unsafety and are a promise to the compiler that the unsafety " "does not leak out of the block." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:224 msgid "" "Unsafe functions, on the other hand, advertise it to the world. An unsafe " "function is written like this:" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:228 msgid "~~~~ unsafe fn kaboom(ptr: *int) -> int { *ptr } ~~~~" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:230 msgid "" "This function can only be called from an `unsafe` block or another `unsafe` " "function." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:232 msgid "# Accessing foreign globals" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:236 msgid "" "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:" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:239 msgid "~~~{.xfail-test} use std::libc;" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:244 #, no-wrap msgid "" "#[link_args = \"-lreadline\"]\n" "extern {\n" " static rl_readline_version: libc::c_int;\n" "}\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:250 #, no-wrap msgid "" "fn main() {\n" " println(fmt!(\"You have readline version %d installed.\",\n" " rl_readline_version as int));\n" "}\n" "~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:254 msgid "" "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." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:258 msgid "~~~{.xfail-test} use std::libc; use std::ptr;" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:263 #, no-wrap msgid "" "#[link_args = \"-lreadline\"]\n" "extern {\n" " static mut rl_prompt: *libc::c_char;\n" "}\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:272 #, no-wrap msgid "" "fn main() {\n" " do \"[my-awesome-shell] $\".as_c_str |buf| {\n" " unsafe { rl_prompt = buf; }\n" " // get a line, process it\n" " unsafe { rl_prompt = ptr::null(); }\n" " }\n" "}\n" "~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:274 msgid "# Foreign calling conventions" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:279 msgid "" "Most foreign code exposes a C ABI, and Rust uses the platform's C calling " "convention by default when calling foreign functions. Some foreign " "functions, most notably the Windows API, use other calling conventions. Rust " "provides the `abi` attribute as a way to hint to the compiler which calling " "convention to use:" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:288 #, no-wrap msgid "" "~~~~\n" "#[cfg(target_os = \"win32\")]\n" "#[abi = \"stdcall\"]\n" "#[link_name = \"kernel32\"]\n" "extern {\n" " fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;\n" "}\n" "~~~~\n" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:292 msgid "" "The `abi` attribute applies to a foreign module (it cannot be applied to a " "single function within a module), and must be either `\"cdecl\"` or `" "\"stdcall\"`. The compiler may eventually support other calling conventions." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:294 msgid "# Interoperability with foreign code" msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:298 msgid "" "Rust guarantees that the layout of a `struct` is compatible with the " "platform's representation in C. A `#[packed]` attribute is available, which " "will lay out the struct members without padding. However, there are " "currently no guarantees about the layout of an `enum`." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:305 msgid "" "Rust's owned and managed boxes use non-nullable pointers as handles which " "point to the contained object. However, they should not be manually created " "because they are managed by internal allocators. Borrowed pointers can " "safely be assumed to be non-nullable pointers directly to the type. However, " "breaking the borrow checking or mutability rules is not guaranteed to be " "safe, so prefer using raw pointers (`*`) if that's needed because the " "compiler can't make as many assumptions about them." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:310 msgid "" "Vectors and strings share the same basic memory layout, and utilities are " "available in the `vec` and `str` modules for working with C APIs. Strings " "are terminated with `\\0` for interoperability with C, but it should not be " "assumed because a slice will not always be nul-terminated. Instead, the " "`str::as_c_str` function should be used." msgstr "" #. type: Plain text #: doc/tutorial-ffi.md:312 msgid "" "The standard library includes type aliases and function definitions for the " "C standard library in the `libc` module, and Rust links against `libc` and " "`libm` by default." msgstr ""