526 lines
15 KiB
Text
526 lines
15 KiB
Text
# 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-pre\n"
|
|
"POT-Creation-Date: 2013-07-17 07:18+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=CHARSET\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:876 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::sys::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 "# Foreign calling conventions"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial-ffi.md:237
|
|
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:246
|
|
#, 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:250
|
|
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:252
|
|
msgid "# Interoperability with foreign code"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial-ffi.md:256
|
|
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:263
|
|
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:268
|
|
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:270
|
|
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 ""
|