From 7c1802ff803c4b10dc65b0d7aadc5b2c70123a90 Mon Sep 17 00:00:00 2001 From: Yoshito Komatsu Date: Wed, 10 Feb 2016 04:49:41 +0000 Subject: [PATCH 1/4] Begin translation of ffi --- 1.6/ja/book/ffi.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/1.6/ja/book/ffi.md b/1.6/ja/book/ffi.md index c3896e4e..7f1b3d29 100644 --- a/1.6/ja/book/ffi.md +++ b/1.6/ja/book/ffi.md @@ -1,12 +1,16 @@ -% Foreign Function Interface - -# Introduction - -This guide will use the [snappy](https://github.com/google/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://github.com/google/snappy/blob/master/snappy-c.h)). +% 外部関数インターフェイス + + + +# 導入 + + + + + + +このガイドでは、他言語のコードのためのバインディングを書く導入に[snappy](https://github.com/google/snappy)という圧縮・展開ライブラリを使います。 +Rustは現在、C++ライブラリを直接呼び出すことができませんが、snappyはCのインターフェイスを持っています(ドキュメントが[`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h)にあります)。 ## A note about libc From 702aa1ad80ce77d985bdc9862ec2e115751e6650 Mon Sep 17 00:00:00 2001 From: Yoshito Komatsu Date: Wed, 10 Feb 2016 11:07:39 +0000 Subject: [PATCH 2/4] Update ffi --- 1.6/ja/book/ffi.md | 679 ++++++++++++++++++++++++++++----------------- 1 file changed, 419 insertions(+), 260 deletions(-) diff --git a/1.6/ja/book/ffi.md b/1.6/ja/book/ffi.md index 7f1b3d29..f911bc4b 100644 --- a/1.6/ja/book/ffi.md +++ b/1.6/ja/book/ffi.md @@ -1,22 +1,25 @@ -% 外部関数インターフェイス - +% 他言語関数インターフェイス + - + # 導入 - - - - - -このガイドでは、他言語のコードのためのバインディングを書く導入に[snappy](https://github.com/google/snappy)という圧縮・展開ライブラリを使います。 -Rustは現在、C++ライブラリを直接呼び出すことができませんが、snappyはCのインターフェイスを持っています(ドキュメントが[`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h)にあります)。 + + + + + +このガイドでは、他言語コードのためのバインディングを書く導入に [snappy](https://github.com/google/snappy) という圧縮・展開ライブラリを使います。 +Rustは現在、C++ライブラリを直接呼び出すことができませんが、snappyはCのインターフェイスを持っています(ドキュメントが [`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h) にあります)。 -## A note about libc + +## libcについてのメモ -Many of these examples use [the `libc` crate][libc], which provides various -type definitions for C types, among other things. If you’re trying these -examples yourself, you’ll need to add `libc` to your `Cargo.toml`: + + + +これらの例の多くは [`libc`クレート][libc] を使っています。これは、主にCの様々な型の定義を提供するものです。 +もしこれらの例を自分で試すのであれば、次のように `libc` を `Cargo.toml` に追加する必要があるでしょう。 ```toml [dependencies] @@ -25,12 +28,15 @@ libc = "0.2.0" [libc]: https://crates.io/crates/libc -and add `extern crate libc;` to your crate root. + +そして、クレートのルートに `extern crate libc;` を追加しましょう。 -## Calling foreign functions + +## 他言語関数の呼出し -The following is a minimal example of calling a foreign function which will -compile if snappy is installed: + + +次のコードは、snappyがインストールされていればコンパイルできる他言語関数を呼び出す最小の例です。 ```no_run # #![feature(libc)] @@ -48,23 +54,29 @@ fn main() { } ``` -The `extern` block is a list of function signatures in a foreign library, in -this case with the platform's C ABI. The `#[link(...)]` attribute is used to -instruct the linker to link against the snappy library so the symbols are -resolved. - -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. - -When declaring the argument types to a foreign function, the Rust compiler can -not check if the declaration is correct, so specifying it correctly is part of -keeping the binding correct at runtime. - -The `extern` block can be extended to cover the entire snappy API: + + + + +`extern` ブロックは他言語ライブラリの中の関数のシグネチャ、この例ではそのプラットフォーム上のC ABIによるもののリストです。 +`#[link(...)]` アトリビュートは、シンボルが解決できるように、リンカに対してsnappyのライブラリをリンクするよう指示するために使われています。 + + + + + + + +他言語関数はアンセーフとみなされるので、それらを呼び出すには、この中に含まれているすべてのものが本当に安全であるということをコンパイラに対して約束するために、 `unsafe {}` で囲まなければなりません。 +Cライブラリは、スレッドセーフでないインターフェイスを公開していることがありますし、ポインタを引数に取る関数のほとんどは、ポインタがダングリングポインタになる可能性を有しているので、すべての入力に対して有効なわけではありません。そして、生ポインタはRustの安全なメモリモデルから外れてしまいます。 + + + + +他言語関数について引数の型を宣言するとき、Rustのコンパイラはその宣言が正しいかどうかを確認することができません。それを正しく指定することは、実行時のバインディングを正しく保つことの一部です。 + + +`extern` ブロックはsnappyのAPI全体をカバーするように拡張することができます。 ```no_run # #![feature(libc)] @@ -91,16 +103,23 @@ extern { # fn main() {} ``` -# Creating a safe interface + +# 安全なインターフェイスの作成 -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. + + + +生のC APIは、メモリの安全性を提供し、ベクタのようなもっと高レベルの概念を使うようにラップしなければなりません。 +ライブラリは安全で高レベルなインターフェイスのみを公開するように選択し、アンセーフな内部の詳細を隠すことができます。 -Wrapping the functions which expect buffers involves using the `slice::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. + + + + +バッファを期待する関数をラップするには、Rustのベクタをメモリへのポインタとして操作するために `slice::raw` モジュールを使います。 +Rustのベクタは隣接したメモリのブロックであることが保証されています。 +その長さは現在含んでいる要素の数で、容量は割り当てられたメモリの要素の合計のサイズです。 +長さは、容量以下です。 ```rust # #![feature(libc)] @@ -115,17 +134,22 @@ pub fn validate_compressed_buffer(src: &[u8]) -> bool { } ``` -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. + + + +上の `validate_compressed_buffer` ラッパは `unsafe` ブロックを使っていますが、関数のシグネチャを `unsafe` から外すことによって、その呼出しがすべての入力に対して安全であることが保証されています。 -The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be -allocated to hold the output too. + + +結果を保持するようにバッファを割り当てなければならないため、 `snappy_compress` 関数と `snappy_uncompress` 関数はもっと複雑です。 -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. + + + + +`snappy_max_compressed_length` 関数は、圧縮後の結果を保持するために必要な最大の容量のベクタを割り当てるために使うことができます。 +そして、そのベクタは結果の引数として`snappy_compress`関数に渡されます。 +結果の引数は、長さをセットするために、圧縮後の本当の長さを取得するためにも渡されます。 ```rust # #![feature(libc)] @@ -151,8 +175,9 @@ pub fn compress(src: &[u8]) -> Vec { } ``` -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. + + +snappyは展開後のサイズを圧縮フォーマットの一部として保存していて、 `snappy_uncompressed_length` が必要となるバッファの正確なサイズを取得するため、展開も同様です。 ```rust # #![feature(libc)] @@ -181,37 +206,50 @@ pub fn uncompress(src: &[u8]) -> Option> { dst.set_len(dstlen as usize); Some(dst) } else { +# // None // SNAPPY_INVALID_INPUT None // SNAPPY_INVALID_INPUT } } } ``` -For reference, the examples used here are also available as a [library on -GitHub](https://github.com/thestinger/rust-snappy). + + +参考のために、ここで使った例は [GitHub上のライブラリ](https://github.com/thestinger/rust-snappy) としても置いておきます。 -# Destructors + +# デストラクタ -Foreign libraries often hand off ownership of resources to the calling code. -When this occurs, we must use Rust's destructors to provide safety and guarantee -the release of these resources (especially in the case of panic). + + + +他言語ライブラリはリソースの所有権を呼出先のコードに手渡してしまうことがあります。 +そういうことが起きる場合には、安全性を提供し、それらのリソースが解放されることを保証するために、Rustのデストラクタを使わなければなりません(特にパニックした場合)。 -For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html). + +デストラクタについて詳しくは、[Dropトレイト](../std/ops/trait.Drop.html)を見てください。 -# Callbacks from C code to Rust functions + +# CのコードからRustの関数へのコールバック -Some external libraries require the usage of callbacks to report back their -current state or intermediate data to the caller. -It is possible to pass functions defined in Rust to an external library. -The requirement for this is that the callback function is marked as `extern` -with the correct calling convention to make it callable from C code. + + + + + +外部のライブラリの中には、現在の状況や中間的なデータを呼出元に報告するためにコールバックを使わなければならないものがあります。 +Rustで定義された関数を外部のライブラリに渡すことは可能です。 +これをするために必要なのは、Cのコードから呼び出すことができるように正しい呼出規則に従って、コールバック関数を `extern` としてマークしておくことです。 -The callback function can then be sent through a registration call -to the C library and afterwards be invoked from there. + + +そして、登録呼出しを通じてコールバック関数をCのライブラリに送ることができるようになり、後でそれらから呼び出すことができるようになります。 -A basic example is: + +基本的な例は次のとおりです。 -Rust code: + +これがRustのコードです。 ```no_run extern fn callback(a: i32) { @@ -227,12 +265,14 @@ extern { fn main() { unsafe { register_callback(callback); - trigger_callback(); // Triggers the callback +# // trigger_callback(); // Triggers the callback + trigger_callback(); // コールバックをトリガーする } } ``` -C code: + +これがCのコードです。 ```c typedef void (*rust_callback)(int32_t); @@ -244,39 +284,49 @@ int32_t register_callback(rust_callback callback) { } void trigger_callback() { - cb(7); // Will call callback(7) in Rust + cb(7); // Rustのcallback(7)を呼び出す } ``` -In this example Rust's `main()` will call `trigger_callback()` in C, -which would, in turn, call back to `callback()` in Rust. + + +この例では、Rustの `main()` がCの `trigger_callback()` を呼び出し、今度はそれが、Rustの `callback()` をコールバックしています。 + +## Rustのオブジェクトを対象にしたコールバック -## Targeting callbacks to Rust objects + + + + +先程の例では、グローバルな関数をCのコードから呼ぶための方法を示してきました。 +しかし、特別なRustのオブジェクトをコールバックの対象にしたいことがあります。 +これは、そのオブジェクトをそれぞれCのオブジェクトのラッパとして表現することで可能になります。 -The former example showed how a global function can be called from C code. -However it is often desired that the callback is targeted to a special -Rust object. This could be the object that represents the wrapper for the -respective C object. + + + + +これは、そのオブジェクトへの生ポインタをCライブラリに渡すことで実現できます。 +そして、Cのライブラリはその通知の中のRustのオブジェクトへのポインタを含むことができるようになります。 +これにより、そのコールバックは参照されるRustのオブジェクトにアンセーフな形でアクセスできるようになります。 -This can be achieved by passing an raw pointer to the object down to the -C library. The C library can then include the pointer to the Rust object in -the notification. This will allow the callback to unsafely access the -referenced Rust object. - -Rust code: + +これがRustのコードです。 ```no_run #[repr(C)] struct RustObject { a: i32, - // other members +# // other members + // その他のメンバ } extern "C" fn callback(target: *mut RustObject, a: i32) { println!("I'm called from C with value {0}", a); unsafe { - // Update the value in RustObject with the value received from the callback +# // Update the value in RustObject with the value received from the callback + // コールバックから受け取った値でRustObjectの中の値をアップデートする (*target).a = a; } } @@ -289,7 +339,8 @@ extern { } fn main() { - // Create the object that will be referenced in the callback +# // Create the object that will be referenced in the callback + // コールバックから参照されるオブジェクトを作成する let mut rust_object = Box::new(RustObject { a: 5 }); unsafe { @@ -299,7 +350,8 @@ fn main() { } ``` -C code: + +これがCのコードです。 ```c typedef void (*rust_callback)(void*, int32_t); @@ -313,102 +365,144 @@ int32_t register_callback(void* callback_target, rust_callback callback) { } void trigger_callback() { - cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust +# // cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust + cb(cb_target, 7); // Rustのcallback(&rustObject, 7)を呼び出す } ``` -## Asynchronous callbacks - -In the previously given examples the callbacks are invoked as a direct reaction -to a function call to the external C library. -The control over the current thread is switched from Rust to C to Rust for the -execution of the callback, but in the end the callback is executed on the -same thread that called the function which triggered the callback. - -Things get more complicated when the external library spawns its own threads -and invokes callbacks from there. -In these cases access to Rust data structures inside the callbacks is -especially unsafe and proper synchronization mechanisms must be used. -Besides classical synchronization mechanisms like mutexes, one possibility in -Rust is to use channels (in `std::sync::mpsc`) to forward data from the C -thread that invoked the callback into a Rust thread. - -If an asynchronous callback targets a special object in the Rust address space -it is also absolutely necessary that no more callbacks are performed by the -C library after the respective Rust object gets destroyed. -This can be achieved by unregistering the callback in the object's -destructor and designing the library in a way that guarantees that no -callback will be performed after deregistration. - -# Linking - -The `link` attribute on `extern` blocks provides the basic building block for -instructing rustc how it will link to native libraries. There are two accepted -forms of the link attribute today: - + +## 非同期コールバック + + + + + + +先程の例では、コールバックは外部のCライブラリへの関数呼出しに対する直接の反応として呼びだされました。 +実行中のスレッドの制御はコールバックの実行のためにRustからCへ、そしてRustへと切り替わりますが、最後には、コールバックはコールバックを引き起こした関数を呼び出したものと同じスレッドで実行されます。 + + + + + + + + +外部のライブラリが独自のスレッドを生成し、そこからコールバックを呼び出すときには、事態はもっと複雑になります。 +そのような場合、コールバックの中のRustのデータ構造へのアクセスは特にアンセーフであり、適切な同期メカニズムを使わなければなりません。 +ミューテックスのような古典的な同期メカニズムの他にも、Rustではコールバックを呼び出したCのスレッドからRustのスレッドにデータを転送するために( `std::sync::mpsc` の中の)チャネルを使うという手もあります。 + + + + + + + +もし、非同期のコールバックがRustのアドレス空間の中の特別なオブジェクトを対象としていれば、それぞれのRustのオブジェクトが破壊された後、Cのライブラリからそれ以上コールバックが実行されないようにすることが絶対に必要です。 +これは、オブジェクトのデストラクタでコールバックの登録を解除し、登録解除後にコールバックが実行されないようにライブラリを設計することで実現できます。 + + +# リンク + + + + +`extern` ブロックの中の `link` アトリビュートは、rustcに対してネイティブライブラリをどのようにリンクするかを指示するための基本的な構成ブロックです。 +今のところ、2つの形式のlinkアトリビュートが認められています。 + + + * `#[link(name = "foo")]` * `#[link(name = "foo", kind = "bar")]` -In both of these cases, `foo` is the name of the native library that we're -linking to, and in the second case `bar` is the type of native library that the -compiler is linking to. There are currently three known types of native -libraries: - -* Dynamic - `#[link(name = "readline")]` -* Static - `#[link(name = "my_build_dependency", kind = "static")]` -* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]` - -Note that frameworks are only available on OSX targets. - -The different `kind` values are meant to differentiate how the native library -participates in linkage. From a linkage perspective, the Rust compiler creates -two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary). -Native dynamic library and framework dependencies are propagated to the final -artifact boundary, while static library dependencies are not propagated at -all, because the static libraries are integrated directly into the subsequent -artifact. - -A few examples of how this model can be used are: - -* A native build dependency. Sometimes some C/C++ glue is needed when writing - some Rust code, but distribution of the C/C++ code in a library format is just - a burden. In this case, the code will be archived into `libfoo.a` and then the - Rust crate would declare a dependency via `#[link(name = "foo", kind = - "static")]`. - - Regardless of the flavor of output for the crate, the native static library - will be included in the output, meaning that distribution of the native static - library is not necessary. - -* A normal dynamic dependency. Common system libraries (like `readline`) are - available on a large number of systems, and often a static copy of these - libraries cannot be found. When this dependency is included in a Rust crate, - partial targets (like rlibs) will not link to the library, but when the rlib - is included in a final target (like a binary), the native library will be - linked in. - -On OSX, frameworks behave with the same semantics as a dynamic library. - -# Unsafe blocks - -Some operations, like dereferencing raw 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. - -Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like -this: + + + + +これらのどちらの形式でも、 `foo` はリンクするネイティブライブラリの名前で、2つ目の形式の `bar` はコンパイラがリンクするネイティブライブラリの種類です。 +3つのネイティブライブラリの種類が知られています。 + + + + +* ダイナミック - `#[link(name = "readline")]` +* スタティック - `#[link(name = "my_build_dependency", kind = "static")]` +* フレームワーク - `#[link(name = "CoreFoundation", kind = "framework")]` + + +フレームワークはOSXターゲットでのみ利用可能であることに注意しましょう。 + + + + + + + + +異なる `kind` の値はリンク時のネイティブライブラリの使われ方の違いを意味します。 +リンクの視点からすると、Rustコンパイラは2種類の生成物を作ります。 +部分生成物(rlib/staticlib)と最終生成物(dylib/binary)です。 +ネイティブダイナミックライブラリとフレームワークの依存関係は最終生成物の境界を伝えますが、スタティックライブラリの依存関係は全く伝えません。なぜなら、スタティックライブラリはその後に続く生成物に直接統合されてしまうからです。 + + +このモデルをどのように使うことができるのかという例は次のとおりです。 + + + + + + +* ネイティブビルドの依存関係。 + ときどき、Rustのコードを書くときにC/C++のグルーが必要になりますが、ライブラリの形式でのC/C++のコードの配布はまさに重荷です。 + このような場合、 `libfoo.a` からコードを得て、それからRustのクレートで `#[link(name = "foo", kind = "static")]` によって依存関係を宣言します。 + + + + + クレートの出力の種類にかかわらず、ネイティブスタティックライブラリは出力に含まれます。これは、ネイティブスタティックライブラリの配布は不要だということを意味します。 + + + + + + + +* 通常のダイナミックな依存関係。 + ( `readline` のような)一般的なシステムライブラリは多くのシステムで利用可能となっていますが、それらのライブラリのスタティックなコピーは見付からないことがしばしばあります。 + この依存関係をRustのクレートに含めるときには、(rlibのような)部分生成物のターゲットはライブラリをリンクしませんが、(binaryのような)最終生成物にrlibを含めるときには、ネイティブライブラリはリンクされます。 + + +OSXでは、フレームワークはダイナミックライブラリと同じ意味で振る舞います。 + + +# アンセーフブロック + + + + +生ポインタの参照外しやアンセーフであるとマークされた関数の呼出しなど、いくつかの作業はアンセーフブロックの中でのみ許されます。 +アンセーフブロックはアンセーフ性を隔離し、コンパイラに対してアンセーフ性がブロックの外に漏れ出さないことを約束します。 + + + +一方、アンセーフな関数はそれを全世界に向けて広告します。 +アンセーフな関数はこのように書きます。 ```rust unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr } ``` -This function can only be called from an `unsafe` block or another `unsafe` function. + +この関数は `unsafe` ブロック又は他の `unsafe` な関数からのみ呼び出すことができます。 -# Accessing foreign globals + +# 他言語のグローバルな値へのアクセス -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: + + + +他言語APIはしばしばグローバルな状態を追跡するようなことをするためのグローバルな値をエクスポートします。 +それらの値にアクセスするために、それらを `extern` ブロックの中で `static` キーワードを付けて宣言します。 ```no_run # #![feature(libc)] @@ -425,9 +519,11 @@ fn main() { } ``` -Alternatively, you may need to alter global state provided by a foreign -interface. To do this, statics can be declared with `mut` so we can mutate -them. + + + +あるいは、他言語インターフェイスが提供するグローバルな状態を変更しなければならないこともあるかもしれません。 +これをするために、スタティックな値を変更することができるように `mut` 付きで宣言することができます。 ```no_run # #![feature(libc)] @@ -453,14 +549,20 @@ fn main() { } ``` -Note that all interaction with a `static mut` is unsafe, both reading and -writing. Dealing with global mutable state requires a great deal of care. + + +`static mut` の付いた作用は全て、読込みと書込みの双方についてアンセーフであることに注意しましょう。 +グローバルでミュータブルな状態の扱いには多大な注意が必要です。 -# Foreign calling conventions + +# 他言語呼出規則 -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 a way to tell the compiler which convention to use: + + + +他言語で書かれたコードの多くはC ABIをエクスポートしていて、Rustは他言語関数の呼出しのときのデフォルトとしてそのプラットフォーム上のCの呼出規則を使います。 +他言語関数の中には、特にWindows APIですが、他の呼出規則を使うものもあります。 +Rustにはコンパイラに対してどの規則を使うかを教える方法があります。 ```rust # #![feature(libc)] @@ -475,9 +577,20 @@ extern "stdcall" { # fn main() { } ``` -This applies to the entire `extern` block. The list of supported ABI constraints -are: - + + +これは `extern` ブロック全体に適用されます。 +サポートされているABIの規則は次のとおりです。 + + + + + + + + + + * `stdcall` * `aapcs` * `cdecl` @@ -488,56 +601,83 @@ are: * `C` * `win64` -Most of the abis in this list are self-explanatory, but the `system` abi may -seem a little odd. This constraint selects whatever the appropriate ABI is for -interoperating with the target's libraries. For example, on win32 with a x86 -architecture, this means that the abi used would be `stdcall`. On x86_64, -however, windows uses the `C` calling convention, so `C` would be used. This -means that in our previous example, we could have used `extern "system" { ... }` -to define a block for all windows systems, not just x86 ones. - -# Interoperability with foreign code - -Rust guarantees that the layout of a `struct` is compatible with the platform's -representation in C only if the `#[repr(C)]` attribute is applied to it. -`#[repr(C, packed)]` can be used to lay out struct members without padding. -`#[repr(C)]` can also be applied to an enum. - -Rust's owned boxes (`Box`) 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. References 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. - -Vectors and strings share the same basic memory layout, and utilities are -available in the `vec` and `str` modules for working with C APIs. However, -strings are not terminated with `\0`. If you need a NUL-terminated string for -interoperability with C, you should use the `CString` type in the `std::ffi` -module. - -The [`libc` crate on crates.io][libc] includes type aliases and function -definitions for the C standard library in the `libc` module, and Rust links -against `libc` and `libm` by default. - -# The "nullable pointer optimization" - -Certain types are defined to not be `null`. This includes references (`&T`, -`&mut T`), boxes (`Box`), and function pointers (`extern "abi" fn()`). -When interfacing with C, pointers that might be null are often used. -As a special case, a generic `enum` that contains exactly two variants, one of -which contains no data and the other containing a single field, is eligible -for the "nullable pointer optimization". When such an enum is instantiated -with one of the non-nullable types, it is represented as a single pointer, -and the non-data variant is represented as the null pointer. So -`Option c_int>` is how one represents a nullable -function pointer using the C ABI. - -# Calling Rust code from C - -You may wish to compile Rust code in a way so that it can be called from C. This is -fairly easy, but requires a few things: + + + + + + + +このリストのABIのほとんどは名前のとおりですが、 `system` ABIは少し変わっています。 +この規則はターゲットのライブラリを相互利用するために適切なABIを選択します。 +例えば、x86アーキテクチャのWin32では、使われるABIは `stdcall` になります。 +しかし、x86_64では、Windowsは `C` の呼出規則を使うので、 `C` が使われます。 +先程の例で言えば、 `extern "system" { ... }` を使って、x86のためだけではなく全てのWindowsシステムのためのブロックを定義することができるということです。 + + +# 他言語コードの相互利用 + + + + + +`#[repr(C)]` アトリビュートが適用されている場合に限り、Rustは `struct` のレイアウトとそのプラットフォーム上のCでの表現方法との互換性を保証します。 +`#[repr(C, packed)]` を使えば、パディングなしで構造体のメンバをレイアウトすることができます。 +`#[repr(C)]` は列挙型にも適用することができます。 + + + + + + + + +Rust独自のボックス( `Box` )はコンテンツオブジェクトを指すハンドルとして非ヌルポインタを使います。 +しかし、それらは内部のアロケータによって管理されるため、手で作るべきではありません。 +参照は型を直接指す非ヌルポインタとみなすことが間違いなくできます。 +しかし、借用チェックやミュータブルについてのルールが破られた場合、安全性は保証されません。もしコンパイラが同数ほどそれらをみなすことができず、それが必要なときには、生ポインタ( `*` )を使いましょう。 + + + + + + +ベクタと文字列は基本的なメモリレイアウトを共有していて、 `vec` モジュールと `str` モジュールの中のユーティリティはC APIで扱うために使うことができます。 +ただし、文字列は `\0` で終わりません。 +Cと相互利用するためにNUL終端の文字列が必要であれば、 `std::ffi` モジュールの `CString` 型を使う必要があります。 + + + + +[crates.ioの`libc`クレート][libc] は `libc` モジュール内にCの標準ライブラリの型の別名や関数の定義を含んでいて、Rustは `libc` と `libm` をデフォルトでリンクします。 + + +# 「ヌルになり得るポインタの最適化」 + + + + + + + + + + + +いくつかの型は非 `null` であると定義されています。 +このようなものには、参照( `&T` 、 `&mut T` )、ボックス( `Box` )、そして関数ポインタ( `extern "abi" fn()` )があります。 +Cとのインターフェイスにおいては、ヌルになり得るポインタが使われることがしばしばあります。 +特別な場合として、ジェネリックな `enum` がちょうど2つのバリアントを持ち、そのうちの1つが値を持っていなくてもう1つが単一のフィールドを持っているとき、それは「ヌルになり得るポインタの最適化」の対象になります。 +そのような列挙型が非ヌルの型でインスタンス化されたとき、それは単一のポインタとして表現され、データを持っていない方のバリアントはヌルポインタとして表現されます。 +`Option c_int>` は、C ABIで使われるヌルになり得る関数ポインタの表現方法の1つです。 + + +# CからのRustのコードの呼出し + + + +RustのコードをCから呼び出せる方法でコンパイルしたいときがあるかもしれません。 +これは割と簡単ですが、いくつか必要なことがあります。 ```rust #[no_mangle] @@ -547,17 +687,23 @@ pub extern fn hello_rust() -> *const u8 { # fn main() {} ``` -The `extern` makes this function adhere to the C calling convention, as -discussed above in "[Foreign Calling -Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` -attribute turns off Rust's name mangling, so that it is easier to link to. + + + + +`extern` は先程「 [他言語呼出規則](ffi.html#foreign-calling-conventions) 」で議論したように、この関数をCの呼出規則に従うようにします。 +`no_mangle` アトリビュートはRustによる名前のマングリングをオフにして、リンクしやすいようにします。 -# FFI and panics + +# FFIとパニック -It’s important to be mindful of `panic!`s when working with FFI. A `panic!` -across an FFI boundary is undefined behavior. If you’re writing code that may -panic, you should run it in another thread, so that the panic doesn’t bubble up -to C: + + + + +FFIを扱うときに `panic!` に注意することは重要です。 +FFIの境界をまたぐ `panic!` の動作は未定義です。 +もしあなたがパニックし得るコードを書いているのであれば、他のスレッドで実行して、パニックがCに波及しないようにすべきです。 ```rust use std::thread; @@ -576,18 +722,22 @@ pub extern fn oh_no() -> i32 { # fn main() {} ``` -# Representing opaque structs + +# オペーク構造体の表現 -Sometimes, a C library wants to provide a pointer to something, but not let you -know the internal details of the thing it wants. The simplest way is to use a -`void *` argument: + + + +ときどき、Cのライブラリが何かのポインタを要求してくるにもかかわらず、その要求されているものの内部的な詳細を教えてくれないことがあります。 +最も単純な方法は `void *` 引数を使うことです。 ```c void foo(void *arg); void bar(void *arg); ``` -We can represent this in Rust with the `c_void` type: + +Rustではこれを `c_void` 型で表現することができます。 ```rust # #![feature(libc)] @@ -600,19 +750,26 @@ extern "C" { # fn main() {} ``` -This is a perfectly valid way of handling the situation. However, we can do a bit -better. To solve this, some C libraries will instead create a `struct`, where -the details and memory layout of the struct are private. This gives some amount -of type safety. These structures are called ‘opaque’. Here’s an example, in C: + + + + +これはその状況に対処するための完全に正当な方法です。 +しかし、もっとよい方法があります。 +これを解決するために、いくつかのCライブラリでは、代わりに `struct` を作っています。そこでは構造体の詳細とメモリレイアウトはプライベートです。 +これは型の安全性をいくらか満たします。 +それらの構造体は「オペーク」と呼ばれます。 +これがCによる例です。 ```c -struct Foo; /* Foo is a structure, but its contents are not part of the public interface */ +struct Foo; /* Fooは構造体だが、その内容は公開インターフェイスの一部ではない */ struct Bar; void foo(struct Foo *arg); void bar(struct Bar *arg); ``` -To do this in Rust, let’s create our own opaque types with `enum`: + +これをRustで実現するために、`enum`で独自のオペーク型を作りましょう。 ```rust pub enum Foo {} @@ -625,7 +782,9 @@ extern "C" { # fn main() {} ``` -By using an `enum` with no variants, we create an opaque type that we can’t -instantiate, as it has no variants. But because our `Foo` and `Bar` types are -different, we’ll get type safety between the two of them, so we cannot -accidentally pass a pointer to `Foo` to `bar()`. + + + + +バリアントなしの `enum` を使って、バリアントがないためにインスタンス化できないオペーク型を作ります。 +しかし、 `Foo` 型と `Bar` 型は異なる型であり、2つものの間の型の安全性を満たすので、 `Foo` のポインタを間違って `bar()` に渡すことはなくなります。 From 19a180356041c1e35154cb664024abce20c005e8 Mon Sep 17 00:00:00 2001 From: Yoshito Komatsu Date: Wed, 10 Feb 2016 11:07:53 +0000 Subject: [PATCH 3/4] Update TranslationTable --- TranslationTable.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TranslationTable.md b/TranslationTable.md index f636cfed..2e054fa2 100644 --- a/TranslationTable.md +++ b/TranslationTable.md @@ -45,6 +45,7 @@ | enum | 列挙型 | expression statement | 式文 | feature | フィーチャ +| foreign | 他言語 | generic parameter | ジェネリックパラメータ | generics | ジェネリクス | growable | 伸張可能 @@ -64,6 +65,7 @@ | lifetime parameter | ライフタイムパラメータ | link | リンク | lint | リント +| mangling | マングリング | match | マッチ | memory | メモリ | method | メソッド @@ -71,6 +73,7 @@ | mutable | ミュータブル | mutability | ミュータビリティ | mutable binding | ミュータブルな束縛 +| opaque | オペーク | output lifetime | 出力ライフタイム | owner | 所有者 | ownership | 所有権 @@ -101,6 +104,7 @@ | type inference | 型推論 | type family | 型族 | Universal Function Call Syntax | 共通の関数呼び出し構文 +| unsafe | アンセーフ | unsigned | 符号無し | unsized type | サイズ不定型 | variable | 変数 From 3ae920570683ee015d2e9b0ce4b1a0b226e9ef43 Mon Sep 17 00:00:00 2001 From: Yoshito Komatsu Date: Thu, 11 Feb 2016 21:26:44 +0000 Subject: [PATCH 4/4] Update ffi --- 1.6/ja/book/ffi.md | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/1.6/ja/book/ffi.md b/1.6/ja/book/ffi.md index f911bc4b..5a6e7415 100644 --- a/1.6/ja/book/ffi.md +++ b/1.6/ja/book/ffi.md @@ -73,7 +73,7 @@ Cライブラリは、スレッドセーフでないインターフェイスを -他言語関数について引数の型を宣言するとき、Rustのコンパイラはその宣言が正しいかどうかを確認することができません。それを正しく指定することは、実行時のバインディングを正しく保つことの一部です。 +他言語関数について引数の型を宣言するとき、Rustのコンパイラはその宣言が正しいかどうかを確認することができません。それを正しく指定することは実行時にバインディングを正しく動作させるために必要なことです。 `extern` ブロックはsnappyのAPI全体をカバーするように拡張することができます。 @@ -148,8 +148,8 @@ pub fn validate_compressed_buffer(src: &[u8]) -> bool { `snappy_max_compressed_length` 関数は、圧縮後の結果を保持するために必要な最大の容量のベクタを割り当てるために使うことができます。 -そして、そのベクタは結果の引数として`snappy_compress`関数に渡されます。 -結果の引数は、長さをセットするために、圧縮後の本当の長さを取得するためにも渡されます。 +そして、そのベクタは結果を受け取るための引数として`snappy_compress`関数に渡されます。 +結果を受け取るための引数は、長さをセットするために、圧縮後の本当の長さを取得するためにも渡されます。 ```rust # #![feature(libc)] @@ -206,7 +206,6 @@ pub fn uncompress(src: &[u8]) -> Option> { dst.set_len(dstlen as usize); Some(dst) } else { -# // None // SNAPPY_INVALID_INPUT None // SNAPPY_INVALID_INPUT } } @@ -308,7 +307,7 @@ void trigger_callback() { これは、そのオブジェクトへの生ポインタをCライブラリに渡すことで実現できます。 -そして、Cのライブラリはその通知の中のRustのオブジェクトへのポインタを含むことができるようになります。 +そして、CのライブラリはRustのオブジェクトへのポインタをその通知の中に含むことができるようになります。 これにより、そのコールバックは参照されるRustのオブジェクトにアンセーフな形でアクセスできるようになります。 @@ -442,7 +441,7 @@ void trigger_callback() { 異なる `kind` の値はリンク時のネイティブライブラリの使われ方の違いを意味します。 リンクの視点からすると、Rustコンパイラは2種類の生成物を作ります。 部分生成物(rlib/staticlib)と最終生成物(dylib/binary)です。 -ネイティブダイナミックライブラリとフレームワークの依存関係は最終生成物の境界を伝えますが、スタティックライブラリの依存関係は全く伝えません。なぜなら、スタティックライブラリはその後に続く生成物に直接統合されてしまうからです。 +ネイティブダイナミックライブラリとフレームワークの依存関係は最終生成物を作るときまで伝播され解決されますが、スタティックライブラリの依存関係は全く伝えません。なぜなら、スタティックライブラリはその後に続く生成物に直接統合されてしまうからです。 このモデルをどのように使うことができるのかという例は次のとおりです。 @@ -453,13 +452,13 @@ void trigger_callback() { * ネイティブビルドの依存関係。 - ときどき、Rustのコードを書くときにC/C++のグルーが必要になりますが、ライブラリの形式でのC/C++のコードの配布はまさに重荷です。 - このような場合、 `libfoo.a` からコードを得て、それからRustのクレートで `#[link(name = "foo", kind = "static")]` によって依存関係を宣言します。 + ときどき、Rustのコードを書くときにC/C++のグルーが必要になりますが、ライブラリの形式でのC/C++のコードの配布は重荷でしかありません。 + このような場合、 コードは `libfoo.a` にアーカイブされ、それからRustのクレートで `#[link(name = "foo", kind = "static")]` によって依存関係を宣言します。 - クレートの出力の種類にかかわらず、ネイティブスタティックライブラリは出力に含まれます。これは、ネイティブスタティックライブラリの配布は不要だということを意味します。 + クレートの成果物の種類にかかわらず、ネイティブスタティックライブラリは成果物に含まれます。これは、ネイティブスタティックライブラリの配布は不要だということを意味します。 @@ -496,12 +495,12 @@ unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr } この関数は `unsafe` ブロック又は他の `unsafe` な関数からのみ呼び出すことができます。 -# 他言語のグローバルな値へのアクセス +# 他言語のグローバル変数へのアクセス -他言語APIはしばしばグローバルな状態を追跡するようなことをするためのグローバルな値をエクスポートします。 +他言語APIはしばしばグローバルな状態を追跡するようなことをするためのグローバル変数をエクスポートします。 それらの値にアクセスするために、それらを `extern` ブロックの中で `static` キーワードを付けて宣言します。 ```no_run @@ -582,15 +581,6 @@ extern "stdcall" { これは `extern` ブロック全体に適用されます。 サポートされているABIの規則は次のとおりです。 - - - - - - - - - * `stdcall` * `aapcs` * `cdecl` @@ -632,10 +622,10 @@ extern "stdcall" { -Rust独自のボックス( `Box` )はコンテンツオブジェクトを指すハンドルとして非ヌルポインタを使います。 +Rust独自のボックス( `Box` )は包んでいるオブジェクトを指すハンドルとして非ヌルポインタを使います。 しかし、それらは内部のアロケータによって管理されるため、手で作るべきではありません。 -参照は型を直接指す非ヌルポインタとみなすことが間違いなくできます。 -しかし、借用チェックやミュータブルについてのルールが破られた場合、安全性は保証されません。もしコンパイラが同数ほどそれらをみなすことができず、それが必要なときには、生ポインタ( `*` )を使いましょう。 +参照は型を直接指す非ヌルポインタとみなすことが安全にできます。 +しかし、借用チェックやミュータブルについてのルールが破られた場合、安全性は保証されません。生ポインタについてはコンパイラは借用チェックやミュータブルほどには仮定を置かないので、必要なときには、生ポインタ( `*` )を使いましょう。