You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-17 14:47:35 +02:00
Publish Comprehensive Rust 🦀
This commit is contained in:
7
src/android/aidl.md
Normal file
7
src/android/aidl.md
Normal file
@ -0,0 +1,7 @@
|
||||
# AIDL
|
||||
|
||||
The [Android Interface Definition Language
|
||||
(AIDL)](https://developer.android.com/guide/components/aidl) is support in Rust:
|
||||
|
||||
* Rust code can call existing AIDL servers,
|
||||
* You can create new AIDL servers in Rust.
|
38
src/android/aidl/birthday_service/Android.bp
Normal file
38
src/android/aidl/birthday_service/Android.bp
Normal file
@ -0,0 +1,38 @@
|
||||
// ANCHOR: libbirthdayservice
|
||||
rust_library {
|
||||
name: "libbirthdayservice",
|
||||
srcs: ["src/lib.rs"],
|
||||
crate_name: "birthdayservice",
|
||||
rustlibs: [
|
||||
"com.example.birthdayservice-rust",
|
||||
"libbinder_rs",
|
||||
],
|
||||
}
|
||||
// ANCHOR_END: libbirthdayservice
|
||||
|
||||
// ANCHOR: birthday_server
|
||||
rust_binary {
|
||||
name: "birthday_server",
|
||||
crate_name: "birthday_server",
|
||||
srcs: ["src/server.rs"],
|
||||
rustlibs: [
|
||||
"com.example.birthdayservice-rust",
|
||||
"libbinder_rs",
|
||||
"libbirthdayservice",
|
||||
],
|
||||
prefer_rlib: true,
|
||||
}
|
||||
// ANCHOR_END: birthday_server
|
||||
|
||||
// ANCHOR: birthday_client
|
||||
rust_binary {
|
||||
name: "birthday_client",
|
||||
crate_name: "birthday_client",
|
||||
srcs: ["src/client.rs"],
|
||||
rustlibs: [
|
||||
"com.example.birthdayservice-rust",
|
||||
"libbinder_rs",
|
||||
],
|
||||
prefer_rlib: true,
|
||||
}
|
||||
// ANCHOR_END: birthday_client
|
10
src/android/aidl/birthday_service/aidl/Android.bp
Normal file
10
src/android/aidl/birthday_service/aidl/Android.bp
Normal file
@ -0,0 +1,10 @@
|
||||
aidl_interface {
|
||||
name: "com.example.birthdayservice",
|
||||
srcs: ["com/example/birthdayservice/*.aidl"],
|
||||
unstable: true,
|
||||
backend: {
|
||||
rust: { // Rust is not enabled by default
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: IBirthdayService
|
||||
package com.example.birthdayservice;
|
||||
|
||||
/** Birthday service interface. */
|
||||
interface IBirthdayService {
|
||||
/** Generate a Happy Birthday message. */
|
||||
String wishHappyBirthday(String name, int years);
|
||||
}
|
42
src/android/aidl/birthday_service/src/client.rs
Normal file
42
src/android/aidl/birthday_service/src/client.rs
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: main
|
||||
//! Birthday service.
|
||||
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;
|
||||
use com_example_birthdayservice::binder;
|
||||
|
||||
const SERVICE_IDENTIFIER: &str = "birthdayservice";
|
||||
|
||||
/// Connect to the BirthdayService.
|
||||
pub fn connect() -> Result<binder::Strong<dyn IBirthdayService>, binder::StatusCode> {
|
||||
binder::get_interface(SERVICE_IDENTIFIER)
|
||||
}
|
||||
|
||||
/// Call the birthday service.
|
||||
fn main() -> Result<(), binder::Status> {
|
||||
let name = std::env::args()
|
||||
.nth(1)
|
||||
.unwrap_or_else(|| String::from("Bob"));
|
||||
let years = std::env::args()
|
||||
.nth(2)
|
||||
.and_then(|arg| arg.parse::<i32>().ok())
|
||||
.unwrap_or(42);
|
||||
|
||||
binder::ProcessState::start_thread_pool();
|
||||
let service = connect().expect("Failed to connect to BirthdayService");
|
||||
let msg = service.wishHappyBirthday(&name, years)?;
|
||||
println!("{msg}");
|
||||
Ok(())
|
||||
}
|
31
src/android/aidl/birthday_service/src/lib.rs
Normal file
31
src/android/aidl/birthday_service/src/lib.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: IBirthdayService
|
||||
//! Implementation of the `IBirthdayService` AIDL interface.
|
||||
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;
|
||||
use com_example_birthdayservice::binder;
|
||||
|
||||
/// The `IBirthdayService` implementation.
|
||||
pub struct BirthdayService;
|
||||
|
||||
impl binder::Interface for BirthdayService {}
|
||||
|
||||
impl IBirthdayService for BirthdayService {
|
||||
fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result<String> {
|
||||
Ok(format!(
|
||||
"Happy Birthday {name}, congratulations with the {years} years!"
|
||||
))
|
||||
}
|
||||
}
|
33
src/android/aidl/birthday_service/src/server.rs
Normal file
33
src/android/aidl/birthday_service/src/server.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: main
|
||||
//! Birthday service.
|
||||
use birthdayservice::BirthdayService;
|
||||
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::BnBirthdayService;
|
||||
use com_example_birthdayservice::binder;
|
||||
|
||||
const SERVICE_IDENTIFIER: &str = "birthdayservice";
|
||||
|
||||
/// Entry point for birthday service.
|
||||
fn main() {
|
||||
let birthday_service = BirthdayService;
|
||||
let birthday_service_binder = BnBirthdayService::new_binder(
|
||||
birthday_service,
|
||||
binder::BinderFeatures::default(),
|
||||
);
|
||||
binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder())
|
||||
.expect("Failed to register service");
|
||||
binder::ProcessState::join_thread_pool()
|
||||
}
|
14
src/android/aidl/changing.md
Normal file
14
src/android/aidl/changing.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Changing API
|
||||
|
||||
Let us extend the API with more functionality: we want to let clients specify a
|
||||
list of lines for the birthday card:
|
||||
|
||||
```java
|
||||
package com.example.birthdayservice;
|
||||
|
||||
/** Birthday service interface. */
|
||||
interface IBirthdayService {
|
||||
/** Generate a Happy Birthday message. */
|
||||
String wishHappyBirthday(String name, int years, in String[] text);
|
||||
}
|
||||
```
|
24
src/android/aidl/client.md
Normal file
24
src/android/aidl/client.md
Normal file
@ -0,0 +1,24 @@
|
||||
# AIDL Client
|
||||
|
||||
Finally, we can create a Rust client for our new service.
|
||||
|
||||
*birthday_service/src/client.rs*:
|
||||
|
||||
```rust,ignore
|
||||
{{#include birthday_service/src/client.rs:main}}
|
||||
```
|
||||
|
||||
*birthday_service/Android.bp*:
|
||||
|
||||
```javascript
|
||||
{{#include birthday_service/Android.bp:birthday_client}}
|
||||
```
|
||||
|
||||
Notice that the client does not depend on `libbirthdayservice`.
|
||||
|
||||
Build, push, and run the client on your device:
|
||||
|
||||
```shell
|
||||
{{#include ../build_all.sh:birthday_client}}
|
||||
Happy Birthday Charlie, congratulations with the 60 years!
|
||||
```
|
29
src/android/aidl/deploy.md
Normal file
29
src/android/aidl/deploy.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Deploy
|
||||
|
||||
We can now build, push, and start the service:
|
||||
|
||||
```shell
|
||||
{{#include ../build_all.sh:birthday_server}}
|
||||
```
|
||||
|
||||
In another terminal, check that the service runs:
|
||||
|
||||
```shell
|
||||
{{#include ../build_all.sh:service_check_birthday_server}}
|
||||
Service birthdayservice: found
|
||||
```
|
||||
|
||||
You can also call the service with `service call`:
|
||||
|
||||
```shell
|
||||
$ {{#include ../build_all.sh:service_call_birthday_server}}
|
||||
Result: Parcel(
|
||||
0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'
|
||||
0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'
|
||||
0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'
|
||||
0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'
|
||||
0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'
|
||||
0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'
|
||||
0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'
|
||||
0x00000070: 00210073 00000000 's.!..... ')
|
||||
```
|
15
src/android/aidl/implementation.md
Normal file
15
src/android/aidl/implementation.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Service Implementation
|
||||
|
||||
We can now implement the AIDL service:
|
||||
|
||||
*birthday_service/src/lib.rs*:
|
||||
|
||||
```rust,ignore
|
||||
{{#include birthday_service/src/lib.rs:IBirthdayService}}
|
||||
```
|
||||
|
||||
*birthday_service/Android.bp*:
|
||||
|
||||
```javascript
|
||||
{{#include birthday_service/Android.bp:libbirthdayservice}}
|
||||
```
|
18
src/android/aidl/interface.md
Normal file
18
src/android/aidl/interface.md
Normal file
@ -0,0 +1,18 @@
|
||||
# AIDL Interfaces
|
||||
|
||||
You declare the API of your service using an AIDL interface:
|
||||
|
||||
*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:
|
||||
|
||||
```java
|
||||
{{#include birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl:IBirthdayService}}
|
||||
```
|
||||
|
||||
*birthday_service/aidl/Android.bp*:
|
||||
|
||||
```javascript
|
||||
{{#include birthday_service/aidl/Android.bp}}
|
||||
```
|
||||
|
||||
Add `vendor_available: true` if your AIDL file is used by a binary in the vendor
|
||||
partition.
|
15
src/android/aidl/server.md
Normal file
15
src/android/aidl/server.md
Normal file
@ -0,0 +1,15 @@
|
||||
# AIDL Server
|
||||
|
||||
Finally, we can create a server which exposes the service:
|
||||
|
||||
*birthday_service/src/server.rs*:
|
||||
|
||||
```rust,ignore
|
||||
{{#include birthday_service/src/server.rs:main}}
|
||||
```
|
||||
|
||||
*birthday_service/Android.bp*:
|
||||
|
||||
```javascript
|
||||
{{#include birthday_service/Android.bp:birthday_server}}
|
||||
```
|
27
src/android/bpfmt.sh
Executable file
27
src/android/bpfmt.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/zsh
|
||||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Simple wrapper for bpfmt which will remove unnecessary newlines before the
|
||||
# mdbook anchors.
|
||||
|
||||
if ! type bpfmt > /dev/null; then
|
||||
echo 'Can not find bpfmt, do you need to run "m bpfmt"?'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for f in comprehensive_rust/**/Android.bp; do
|
||||
bpfmt -s -w $f
|
||||
sed -zi 's|\n// ANCHOR_END|// ANCHOR_END|g' $f
|
||||
done
|
16
src/android/build-rules.md
Normal file
16
src/android/build-rules.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Build Rules
|
||||
|
||||
The Android build system (Soong) supports Rust via a number of modules:
|
||||
|
||||
| Module Type | Description |
|
||||
|-------------------|----------------------------------------------------------------------------------------------------|
|
||||
| `rust_binary` | Produces a Rust binary. |
|
||||
| `rust_library` | Produces a Rust library, and provides both `rlib` and `dylib` variants. |
|
||||
| `rust_ffi` | Produces a Rust C library usable by `cc` modules, and provides both static and shared variants. |
|
||||
| `rust_proc_macro` | Produces a `proc-macro` Rust library. These are analogous to compiler plugins. |
|
||||
| `rust_test` | Produces a Rust test binary that uses the standard Rust test harness. |
|
||||
| `rust_fuzz` | Produces a Rust fuzz binary leveraging `libfuzzer`. |
|
||||
| `rust_protobuf` | Generates source and produces a Rust library that provides an interface for a particular protobuf. |
|
||||
| `rust_bindgen` | Generates source and produces a Rust library containing Rust bindings to C libraries. |
|
||||
|
||||
We will look at `rust_binary` and `rust_library` next.
|
23
src/android/build-rules/binary.md
Normal file
23
src/android/build-rules/binary.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Rust Binaries
|
||||
|
||||
Let us start with a simple application. At the root of an AOSP checkout, create
|
||||
the following files:
|
||||
|
||||
_hello_rust/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include binary/Android.bp}}
|
||||
```
|
||||
|
||||
_hello_rust/src/main.rs_:
|
||||
|
||||
```rust
|
||||
{{#include binary/src/main.rs:main}}
|
||||
```
|
||||
|
||||
You can now build, push, and run the binary:
|
||||
|
||||
```shell
|
||||
{{#include ../build_all.sh:hello_rust}}
|
||||
Hello from Rust!
|
||||
```
|
5
src/android/build-rules/binary/Android.bp
Normal file
5
src/android/build-rules/binary/Android.bp
Normal file
@ -0,0 +1,5 @@
|
||||
rust_binary {
|
||||
name: "hello_rust",
|
||||
crate_name: "hello_rust",
|
||||
srcs: ["src/main.rs"],
|
||||
}
|
21
src/android/build-rules/binary/src/main.rs
Normal file
21
src/android/build-rules/binary/src/main.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: main
|
||||
//! Rust demo.
|
||||
|
||||
/// Prints a greeting to standard output.
|
||||
fn main() {
|
||||
println!("Hello from Rust!");
|
||||
}
|
37
src/android/build-rules/library.md
Normal file
37
src/android/build-rules/library.md
Normal file
@ -0,0 +1,37 @@
|
||||
# Rust Libraries
|
||||
|
||||
You use `rust_library` to create a new Rust library for Android.
|
||||
|
||||
Here we declare a dependency on two libraries:
|
||||
|
||||
* `libgreeting`, which we define below,
|
||||
* `libtextwrap`, which is a crate already vendored in
|
||||
[`external/rust/crates/`][crates].
|
||||
|
||||
[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/
|
||||
|
||||
_hello_rust/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include library/Android.bp}}
|
||||
```
|
||||
|
||||
_hello_rust/src/main.rs_:
|
||||
|
||||
```rust,ignore
|
||||
{{#include library/src/main.rs:main}}
|
||||
```
|
||||
|
||||
_hello_rust/src/lib.rs_:
|
||||
|
||||
```rust,ignore
|
||||
{{#include library/src/lib.rs:greeting}}
|
||||
```
|
||||
|
||||
You build, push, and run the binary like before:
|
||||
|
||||
```shell
|
||||
{{#include ../build_all.sh:hello_rust_with_dep}}
|
||||
Hello Bob, it is very
|
||||
nice to meet you!
|
||||
```
|
16
src/android/build-rules/library/Android.bp
Normal file
16
src/android/build-rules/library/Android.bp
Normal file
@ -0,0 +1,16 @@
|
||||
rust_binary {
|
||||
name: "hello_rust_with_dep",
|
||||
crate_name: "hello_rust_with_dep",
|
||||
srcs: ["src/main.rs"],
|
||||
rustlibs: [
|
||||
"libgreetings",
|
||||
"libtextwrap",
|
||||
],
|
||||
prefer_rlib: true,
|
||||
}
|
||||
|
||||
rust_library {
|
||||
name: "libgreetings",
|
||||
crate_name: "greetings",
|
||||
srcs: ["src/lib.rs"],
|
||||
}
|
21
src/android/build-rules/library/src/lib.rs
Normal file
21
src/android/build-rules/library/src/lib.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: greeting
|
||||
//! Greeting library.
|
||||
|
||||
/// Greet `name`.
|
||||
pub fn greeting(name: &str) -> String {
|
||||
format!("Hello {name}, it is very nice to meet you!")
|
||||
}
|
24
src/android/build-rules/library/src/main.rs
Normal file
24
src/android/build-rules/library/src/main.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: main
|
||||
//! Rust demo.
|
||||
|
||||
use greetings::greeting;
|
||||
use textwrap::fill;
|
||||
|
||||
/// Prints a greeting to standard output.
|
||||
fn main() {
|
||||
println!("{}", fill(&greeting("Bob"), 24));
|
||||
}
|
130
src/android/build_all.sh
Executable file
130
src/android/build_all.sh
Executable file
@ -0,0 +1,130 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -e
|
||||
|
||||
function run_example() {
|
||||
while read -r line; do
|
||||
if [[ "$line" != \#* ]]; then
|
||||
echo "$line"
|
||||
eval "${line#$ }"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
cd $ANDROID_BUILD_TOP
|
||||
source build/envsetup.sh
|
||||
lunch aosp_cf_x86_64_phone-userdebug
|
||||
#acloud reconnect --autoconnect adb
|
||||
|
||||
adb root
|
||||
adb shell rm -rf '/data/local/tmp/*'
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: hello_rust
|
||||
$ m hello_rust
|
||||
$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp
|
||||
$ adb shell /data/local/tmp/hello_rust
|
||||
# ANCHOR_END: hello_rust
|
||||
EOF
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: hello_rust_with_dep
|
||||
$ m hello_rust_with_dep
|
||||
$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/tmp
|
||||
$ adb shell /data/local/tmp/hello_rust_with_dep
|
||||
# ANCHOR_END: hello_rust_with_dep
|
||||
EOF
|
||||
|
||||
function birthday_server() {
|
||||
run_example <<EOF
|
||||
# ANCHOR: birthday_server
|
||||
$ m birthday_server
|
||||
$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp
|
||||
$ adb shell /data/local/tmp/birthday_server
|
||||
# ANCHOR_END: birthday_server
|
||||
EOF
|
||||
}
|
||||
|
||||
pkill -f birthday_server || true
|
||||
birthday_server &
|
||||
BIRTHDAY_SERVER_PID=$!
|
||||
|
||||
while adb shell service check birthdayservice | grep -q 'not found'; do
|
||||
echo "Waiting on birthdayservice..."
|
||||
sleep 3
|
||||
done
|
||||
echo "Found birthdayservice..."
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: service_check_birthday_server
|
||||
$ adb shell service check birthdayservice
|
||||
# ANCHOR_END: service_check_birthday_server
|
||||
EOF
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: service_call_birthday_server
|
||||
$ adb shell service call birthdayservice 1 s16 Bob i32 24
|
||||
# ANCHOR_END: service_call_birthday_server
|
||||
EOF
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: birthday_client
|
||||
$ m birthday_client
|
||||
$ adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp
|
||||
$ adb shell /data/local/tmp/birthday_client Charlie 60
|
||||
# ANCHOR_END: birthday_client
|
||||
EOF
|
||||
|
||||
pkill -f birthday_server
|
||||
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: hello_rust_logs
|
||||
$ m hello_rust_logs
|
||||
$ adb push $ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/tmp
|
||||
$ adb shell /data/local/tmp/hello_rust_logs
|
||||
# ANCHOR_END: hello_rust_logs
|
||||
EOF
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: print_birthday_card
|
||||
$ m print_birthday_card
|
||||
$ adb push $ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/tmp
|
||||
$ adb shell /data/local/tmp/print_birthday_card
|
||||
# ANCHOR_END: print_birthday_card
|
||||
EOF
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: libbirthday_bindgen_test
|
||||
$ atest libbirthday_bindgen_test
|
||||
# ANCHOR_END: libbirthday_bindgen_test
|
||||
EOF
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: analyze_numbers
|
||||
$ m analyze_numbers
|
||||
$ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp
|
||||
$ adb shell /data/local/tmp/analyze_numbers
|
||||
# ANCHOR_END: analyze_numbers
|
||||
EOF
|
||||
|
||||
run_example <<EOF
|
||||
# ANCHOR: helloworld_jni
|
||||
$ m helloworld_jni
|
||||
$ adb sync # requires adb root && adb remount
|
||||
$ adb shell /system/bin/helloworld_jni
|
||||
# ANCHOR_END: helloworld_jni
|
||||
EOF
|
10
src/android/interoperability.md
Normal file
10
src/android/interoperability.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Interoperability
|
||||
|
||||
Rust has excellent support for interoperability with other languages. This means
|
||||
that you can
|
||||
|
||||
* Call Rust functions from other languages
|
||||
* Call functions written in other languages from Rust
|
||||
|
||||
When you call functions in a foreign language we say that you're using a
|
||||
_foreign function interface_, also known as FFI.
|
13
src/android/interoperability/cpp.md
Normal file
13
src/android/interoperability/cpp.md
Normal file
@ -0,0 +1,13 @@
|
||||
# With C++
|
||||
|
||||
The [CXX crate][1] makes it possible to do safe interoperability between Rust
|
||||
and C++.
|
||||
|
||||
The overall approach looks like this:
|
||||
|
||||
<img src="cpp/overview.svg">
|
||||
|
||||
See the [CXX tutorial][2] for an full example of using this.
|
||||
|
||||
[1]: https://cxx.rs/
|
||||
[2]: https://cxx.rs/tutorial.html
|
1
src/android/interoperability/cpp/overview.svg
Symbolic link
1
src/android/interoperability/cpp/overview.svg
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../third_party/cxx/overview.svg
|
39
src/android/interoperability/java.md
Normal file
39
src/android/interoperability/java.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Interoperability with Java
|
||||
|
||||
Java can load shared objects via [Java Native Interface
|
||||
(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`
|
||||
crate](https://docs.rs/jni/) allows you to create a compatible library.
|
||||
|
||||
First, we create a Rust function to export to Java:
|
||||
|
||||
_interoperability/java/src/lib.rs_:
|
||||
|
||||
```rust,compile_fail
|
||||
{{#include java/src/lib.rs:hello}}
|
||||
```
|
||||
|
||||
_interoperability/java/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include java/Android.bp:libhello_jni}}
|
||||
```
|
||||
|
||||
Finally, we can call this function from Java:
|
||||
|
||||
_interoperability/java/HelloWorld.java_:
|
||||
|
||||
```java
|
||||
{{#include java/HelloWorld.java:HelloWorld}}
|
||||
```
|
||||
|
||||
_interoperability/java/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include java/Android.bp:helloworld_jni}}
|
||||
```
|
||||
|
||||
Finally, you can build, sync, and run the binary:
|
||||
|
||||
```shell
|
||||
{{#include ../build_all.sh:helloworld_jni}}
|
||||
```
|
17
src/android/interoperability/java/Android.bp
Normal file
17
src/android/interoperability/java/Android.bp
Normal file
@ -0,0 +1,17 @@
|
||||
// ANCHOR: libhello_jni
|
||||
rust_ffi_shared {
|
||||
name: "libhello_jni",
|
||||
crate_name: "hello_jni",
|
||||
srcs: ["src/lib.rs"],
|
||||
rustlibs: ["libjni"],
|
||||
}
|
||||
// ANCHOR_END: libhello_jni
|
||||
|
||||
// ANCHOR: helloworld_jni
|
||||
java_binary {
|
||||
name: "helloworld_jni",
|
||||
srcs: ["HelloWorld.java"],
|
||||
main_class: "HelloWorld",
|
||||
required: ["libhello_jni"],
|
||||
}
|
||||
// ANCHOR_END: helloworld_jni
|
29
src/android/interoperability/java/HelloWorld.java
Normal file
29
src/android/interoperability/java/HelloWorld.java
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ANCHOR: HelloWorld
|
||||
class HelloWorld {
|
||||
private static native String hello(String name);
|
||||
|
||||
static {
|
||||
System.loadLibrary("hello_jni");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String output = HelloWorld.hello("Alice");
|
||||
System.out.println(output);
|
||||
}
|
||||
}
|
33
src/android/interoperability/java/src/lib.rs
Normal file
33
src/android/interoperability/java/src/lib.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: hello
|
||||
//! Rust <-> Java FFI demo.
|
||||
|
||||
use jni::objects::{JClass, JString};
|
||||
use jni::sys::jstring;
|
||||
use jni::JNIEnv;
|
||||
|
||||
/// HelloWorld::hello method implementation.
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_HelloWorld_hello(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
name: JString,
|
||||
) -> jstring {
|
||||
let input: String = env.get_string(name).unwrap().into();
|
||||
let greeting = format!("Hello, {input}!");
|
||||
let output = env.new_string(greeting).unwrap();
|
||||
output.into_inner()
|
||||
}
|
26
src/android/interoperability/with-c.md
Normal file
26
src/android/interoperability/with-c.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Interoperability with C
|
||||
|
||||
Rust has full support for linking object files with a C calling convention.
|
||||
Similarly, you can export Rust functions and call them from C.
|
||||
|
||||
You can do it by hand if you want:
|
||||
|
||||
```rust
|
||||
extern "C" {
|
||||
fn abs(x: i32) -> i32;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = -42;
|
||||
let abs_x = unsafe { abs(x) };
|
||||
println!("{x}, {abs_x}");
|
||||
}
|
||||
```
|
||||
|
||||
We already saw this in the [Safe FFI Wrapper
|
||||
exercise](../../exercises/day-3/safe-ffi-wrapper.md).
|
||||
|
||||
> This assumes full knowledge of the target platform. Not recommended for
|
||||
> production.
|
||||
|
||||
We will look at better options next.
|
75
src/android/interoperability/with-c/bindgen.md
Normal file
75
src/android/interoperability/with-c/bindgen.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Using Bindgen
|
||||
|
||||
The [bindgen](https://rust-lang.github.io/rust-bindgen/introduction.html) tool
|
||||
can auto-generate bindings from a C header file.
|
||||
|
||||
First create a small C library:
|
||||
|
||||
_interoperability/bindgen/libbirthday.h_:
|
||||
|
||||
```c
|
||||
{{#include bindgen/libbirthday.h:card}}
|
||||
```
|
||||
|
||||
_interoperability/bindgen/libbirthday.c_:
|
||||
|
||||
```c
|
||||
{{#include bindgen/libbirthday.c:print_card}}
|
||||
```
|
||||
|
||||
Add this to your `Android.bp` file:
|
||||
|
||||
_interoperability/bindgen/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include bindgen/Android.bp:libbirthday}}
|
||||
```
|
||||
|
||||
Create a wrapper header file for the library (not strictly needed in this
|
||||
example):
|
||||
|
||||
_interoperability/bindgen/libbirthday_wrapper.h_:
|
||||
|
||||
```c
|
||||
{{#include bindgen/libbirthday_wrapper.h:include}}
|
||||
```
|
||||
|
||||
You can now auto-generate the bindings:
|
||||
|
||||
_interoperability/bindgen/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include bindgen/Android.bp:libbirthday_bindgen}}
|
||||
```
|
||||
|
||||
Finally, we can use the bindings in our Rust program:
|
||||
|
||||
_interoperability/bindgen/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include bindgen/Android.bp:print_birthday_card}}
|
||||
```
|
||||
|
||||
_interoperability/bindgen/main.rs_:
|
||||
|
||||
```rust,compile_fail
|
||||
{{#include bindgen/main.rs:main}}
|
||||
```
|
||||
|
||||
Build, push, and run the binary on your device:
|
||||
|
||||
```shell
|
||||
{{#include ../../build_all.sh:print_birthday_card}}
|
||||
```
|
||||
|
||||
Finally, we can run auto-generated tests to ensure the bindings work:
|
||||
|
||||
_interoperability/bindgen/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include bindgen/Android.bp:libbirthday_bindgen_test}}
|
||||
```
|
||||
|
||||
```shell
|
||||
{{#include ../../build_all.sh:libbirthday_bindgen_test}}
|
||||
```
|
36
src/android/interoperability/with-c/bindgen/Android.bp
Normal file
36
src/android/interoperability/with-c/bindgen/Android.bp
Normal file
@ -0,0 +1,36 @@
|
||||
// ANCHOR: libbirthday
|
||||
cc_library {
|
||||
name: "libbirthday",
|
||||
srcs: ["libbirthday.c"],
|
||||
}
|
||||
// ANCHOR_END: libbirthday
|
||||
|
||||
// ANCHOR: libbirthday_bindgen
|
||||
rust_bindgen {
|
||||
name: "libbirthday_bindgen",
|
||||
crate_name: "birthday_bindgen",
|
||||
wrapper_src: "libbirthday_wrapper.h",
|
||||
source_stem: "bindings",
|
||||
static_libs: ["libbirthday"],
|
||||
}
|
||||
// ANCHOR_END: libbirthday_bindgen
|
||||
|
||||
// ANCHOR: libbirthday_bindgen_test
|
||||
rust_test {
|
||||
name: "libbirthday_bindgen_test",
|
||||
srcs: [":libbirthday_bindgen"],
|
||||
crate_name: "libbirthday_bindgen_test",
|
||||
test_suites: ["general-tests"],
|
||||
auto_gen_config: true,
|
||||
clippy_lints: "none", // Generated file, skip linting
|
||||
lints: "none",
|
||||
}
|
||||
// ANCHOR_END: libbirthday_bindgen_test
|
||||
|
||||
// ANCHOR: print_birthday_card
|
||||
rust_binary {
|
||||
name: "print_birthday_card",
|
||||
srcs: ["main.rs"],
|
||||
rustlibs: ["libbirthday_bindgen"],
|
||||
}
|
||||
// ANCHOR_END: print_birthday_card
|
20
src/android/interoperability/with-c/bindgen/c-library.md
Normal file
20
src/android/interoperability/with-c/bindgen/c-library.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Create a C library
|
||||
|
||||
_interoperability/c/libbirthday/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include c/libbirthday/Android.bp:libbirthday}}
|
||||
```
|
||||
|
||||
_interoperability/c/libbirthday/libbirthday.h_:
|
||||
|
||||
```c
|
||||
{{#include c/libbirthday/libbirthday.h}}
|
||||
```
|
||||
|
||||
_interoperability/c/libbirthday/libbirthday.c_:
|
||||
|
||||
```c
|
||||
{{#include c/libbirthday/libbirthday.c}}
|
||||
```
|
||||
|
26
src/android/interoperability/with-c/bindgen/libbirthday.c
Normal file
26
src/android/interoperability/with-c/bindgen/libbirthday.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ANCHOR: print_card
|
||||
#include <stdio.h>
|
||||
#include "libbirthday.h"
|
||||
|
||||
void print_card(const card* card) {
|
||||
printf("+--------------\n");
|
||||
printf("| Happy Birthday %s!\n", card->name);
|
||||
printf("| Congratulations with the %i years!\n", card->years);
|
||||
printf("+--------------\n");
|
||||
}
|
23
src/android/interoperability/with-c/bindgen/libbirthday.h
Normal file
23
src/android/interoperability/with-c/bindgen/libbirthday.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ANCHOR: card
|
||||
typedef struct card {
|
||||
const char* name;
|
||||
int years;
|
||||
} card;
|
||||
|
||||
void print_card(const card* card);
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ANCHOR: include
|
||||
#include "libbirthday.h"
|
29
src/android/interoperability/with-c/bindgen/main.rs
Normal file
29
src/android/interoperability/with-c/bindgen/main.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: main
|
||||
//! Bindgen demo.
|
||||
|
||||
use birthday_bindgen::{card, print_card};
|
||||
|
||||
fn main() {
|
||||
let name = std::ffi::CString::new("Peter").unwrap();
|
||||
let card = card {
|
||||
name: name.as_ptr(),
|
||||
years: 42,
|
||||
};
|
||||
unsafe {
|
||||
print_card(&card as *const card);
|
||||
}
|
||||
}
|
1
src/android/interoperability/with-c/calling-rust.md
Normal file
1
src/android/interoperability/with-c/calling-rust.md
Normal file
@ -0,0 +1 @@
|
||||
# Calling Rust from C
|
21
src/android/interoperability/with-c/hand-written.md
Normal file
21
src/android/interoperability/with-c/hand-written.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Handwritten FFI
|
||||
|
||||
We can declare external functions by hand:
|
||||
|
||||
```rust
|
||||
extern "C" {
|
||||
fn abs(x: i32) -> i32;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = -42;
|
||||
let abs_x = unsafe { abs(x) };
|
||||
println!("{x}, {abs_x}");
|
||||
}
|
||||
```
|
||||
|
||||
We already saw this in the [Safe FFI Wrapper
|
||||
exercise](../../exercises/day-3/safe-ffi-wrapper.md).
|
||||
|
||||
> This assumes full knowledge of the target platform. Not recommended for
|
||||
> production.
|
42
src/android/interoperability/with-c/rust.md
Normal file
42
src/android/interoperability/with-c/rust.md
Normal file
@ -0,0 +1,42 @@
|
||||
# Calling Rust
|
||||
|
||||
Exporting Rust functions and types to C is easy:
|
||||
|
||||
_interoperability/rust/libanalyze/analyze.rs_
|
||||
|
||||
```rust,editable
|
||||
{{#include rust/libanalyze/analyze.rs:analyze_numbers}}
|
||||
```
|
||||
|
||||
_interoperability/rust/libanalyze/analyze.h_
|
||||
|
||||
```c
|
||||
{{#include rust/libanalyze/analyze.h:analyze_numbers}}
|
||||
```
|
||||
|
||||
_interoperability/rust/libanalyze/Android.bp_
|
||||
|
||||
```javascript
|
||||
{{#include rust/libanalyze/Android.bp}}
|
||||
```
|
||||
|
||||
We can now call this from a C binary:
|
||||
|
||||
_interoperability/rust/analyze/main.c_
|
||||
|
||||
```c
|
||||
{{#include rust/analyze/main.c:main}}
|
||||
```
|
||||
|
||||
_interoperability/rust/analyze/Android.bp_
|
||||
|
||||
```javascript
|
||||
{{#include rust/analyze/Android.bp}}
|
||||
```
|
||||
|
||||
|
||||
Build, push, and run the binary on your device:
|
||||
|
||||
```shell
|
||||
{{#include ../../build_all.sh:analyze_numbers}}
|
||||
```
|
@ -0,0 +1,5 @@
|
||||
cc_binary {
|
||||
name: "analyze_numbers",
|
||||
srcs: ["main.c"],
|
||||
static_libs: ["libanalyze_ffi"],
|
||||
}
|
24
src/android/interoperability/with-c/rust/analyze/main.c
Normal file
24
src/android/interoperability/with-c/rust/analyze/main.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ANCHOR: main
|
||||
#include "analyze.h"
|
||||
|
||||
int main() {
|
||||
analyze_numbers(10, 20);
|
||||
analyze_numbers(123, 123);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
rust_ffi {
|
||||
name: "libanalyze_ffi",
|
||||
crate_name: "analyze_ffi",
|
||||
srcs: ["analyze.rs"],
|
||||
include_dirs: ["."],
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ANCHOR: analyze_numbers
|
||||
#ifndef ANALYSE_H
|
||||
#define ANALYSE_H
|
||||
|
||||
extern "C" {
|
||||
void analyze_numbers(int x, int y);
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,29 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: analyze_numbers
|
||||
//! Rust FFI demo.
|
||||
#![deny(improper_ctypes_definitions)]
|
||||
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Analyze the numbers.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn analyze_numbers(x: c_int, y: c_int) {
|
||||
if x < y {
|
||||
println!("x ({x}) is smallest!");
|
||||
} else {
|
||||
println!("y ({y}) is probably larger than x ({x})");
|
||||
}
|
||||
}
|
31
src/android/logging.md
Normal file
31
src/android/logging.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Logging
|
||||
|
||||
You should use the `log` crate to automatically log to `logcat` (on-device) or
|
||||
`stdout` (on-host):
|
||||
|
||||
_hello_rust_logs/Android.bp_:
|
||||
|
||||
```javascript
|
||||
{{#include logging/Android.bp}}
|
||||
```
|
||||
|
||||
_hello_rust_logs/src/main.rs_:
|
||||
|
||||
```rust,ignore
|
||||
{{#include logging/src/main.rs:main}}
|
||||
```
|
||||
|
||||
Build, push, and run the binary on your device:
|
||||
|
||||
```shell
|
||||
{{#include build_all.sh:hello_rust_logs}}
|
||||
```
|
||||
|
||||
The logs show up in `adb logcat`:
|
||||
|
||||
```shell
|
||||
$ adb logcat -s rust
|
||||
09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.
|
||||
09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going fine.
|
||||
09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went wrong!
|
||||
```
|
11
src/android/logging/Android.bp
Normal file
11
src/android/logging/Android.bp
Normal file
@ -0,0 +1,11 @@
|
||||
rust_binary {
|
||||
name: "hello_rust_logs",
|
||||
crate_name: "hello_rust_logs",
|
||||
srcs: ["src/main.rs"],
|
||||
rustlibs: [
|
||||
"liblog_rust",
|
||||
"liblogger",
|
||||
],
|
||||
prefer_rlib: true,
|
||||
host_supported: true,
|
||||
}
|
29
src/android/logging/src/main.rs
Normal file
29
src/android/logging/src/main.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: main
|
||||
//! Rust logging demo.
|
||||
|
||||
use log::{debug, error};
|
||||
|
||||
/// Logs a greeting.
|
||||
fn main() {
|
||||
logger::init(
|
||||
logger::Config::default()
|
||||
.with_tag_on_device("rust")
|
||||
.with_min_level(log::Level::Trace),
|
||||
);
|
||||
debug!("Starting program.");
|
||||
error!("Something went wrong!");
|
||||
}
|
13
src/android/setup.md
Normal file
13
src/android/setup.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Setup
|
||||
|
||||
We will be using an Android Virtual Device to test our code. Make sure you have
|
||||
access to one or create a new one with:
|
||||
|
||||
```shell
|
||||
$ source build/envsetup.sh
|
||||
$ lunch aosp_cf_x86_64_phone-userdebug
|
||||
$ acloud create
|
||||
```
|
||||
|
||||
Please see the [Android Developer
|
||||
Codelab](https://source.android.com/docs/setup/start) for details.
|
Reference in New Issue
Block a user