rust/doc/po/tutorial-ffi.md.pot

603 lines
17 KiB
Plaintext

# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR The Rust Project Developers
# This file is distributed under the same license as the Rust package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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(vec::raw::to_ptr(src), 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 = vec::raw::to_ptr(src);\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 = vec::raw::to_mut_ptr(dst);\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-ffi.md:113
#, no-wrap
msgid ""
" snappy_compress(psrc, srclen, pdst, &mut dstlen);\n"
" vec::raw::set_len(&mut dst, 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 = vec::raw::to_ptr(src);\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 = vec::raw::to_mut_ptr(dst);\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-ffi.md:138
#, no-wrap
msgid ""
" if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {\n"
" vec::raw::set_len(&mut dst, 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<T> {\n"
" priv ptr: *mut T\n"
"}\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-ffi.md:172
#, no-wrap
msgid ""
"impl<T: Send> Unique<T> {\n"
" pub fn new(value: T) -> Unique<T> {\n"
" unsafe {\n"
" let ptr = malloc(std::mem::size_of::<T>() 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<T: Send> Drop for Unique<T> {\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 ""