mirror of
https://github.com/google/comprehensive-rust.git
synced 2024-11-21 13:25:53 +02:00
Updates for Rust 1.82 (#2449)
Rust 1.82 adds `&raw` expressions, and marks some attributes as unsafe.
This commit is contained in:
parent
2bba470415
commit
f8882190f3
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -55,6 +55,9 @@ jobs:
|
||||
- name: Setup Rust cache
|
||||
uses: ./.github/workflows/setup-rust-cache
|
||||
|
||||
- name: Update Rust
|
||||
run: rustup update
|
||||
|
||||
- name: Build Rust code
|
||||
run: cargo build
|
||||
|
||||
@ -89,7 +92,9 @@ jobs:
|
||||
sudo apt install gcc-aarch64-linux-gnu
|
||||
|
||||
- name: Install toolchain
|
||||
run: rustup target add ${{ matrix.target }}
|
||||
run: |
|
||||
rustup update
|
||||
rustup target add ${{ matrix.target }}
|
||||
|
||||
- name: Build Rust code
|
||||
working-directory: ${{ matrix.directory }}
|
||||
@ -140,6 +145,9 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt install gettext
|
||||
|
||||
- name: Update Rust
|
||||
run: rustup update
|
||||
|
||||
- name: Install mdbook
|
||||
uses: ./.github/workflows/install-mdbook
|
||||
|
||||
|
@ -20,7 +20,8 @@ use jni::sys::jstring;
|
||||
use jni::JNIEnv;
|
||||
|
||||
/// HelloWorld::hello method implementation.
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "system" fn Java_HelloWorld_hello(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
|
@ -6,14 +6,13 @@ 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;
|
||||
unsafe extern "C" {
|
||||
safe fn abs(x: i32) -> i32;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = -42;
|
||||
// SAFETY: `abs` doesn't have any safety requirements.
|
||||
let abs_x = unsafe { abs(x) };
|
||||
let abs_x = abs(x);
|
||||
println!("{x}, {abs_x}");
|
||||
}
|
||||
```
|
||||
|
@ -3,14 +3,13 @@
|
||||
We can declare external functions by hand:
|
||||
|
||||
```rust
|
||||
extern "C" {
|
||||
fn abs(x: i32) -> i32;
|
||||
unsafe extern "C" {
|
||||
safe fn abs(x: i32) -> i32;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = -42;
|
||||
// SAFETY: `abs` doesn't have any safety requirements.
|
||||
let abs_x = unsafe { abs(x) };
|
||||
let abs_x = abs(x);
|
||||
println!("{x}, {abs_x}");
|
||||
}
|
||||
```
|
||||
|
@ -42,8 +42,8 @@ Build, push, and run the binary on your device:
|
||||
|
||||
<details>
|
||||
|
||||
`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will
|
||||
just be the name of the function. You can also use
|
||||
`#[export_name = "some_name"]` to specify whatever name you want.
|
||||
`#[unsafe(no_mangle)]` disables Rust's usual name mangling, so the exported
|
||||
symbol will just be the name of the function. You can also use
|
||||
`#[unsafe(export_name = "some_name")]` to specify whatever name you want.
|
||||
|
||||
</details>
|
||||
|
@ -19,7 +19,8 @@
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Analyze the numbers.
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn analyze_numbers(x: c_int, y: c_int) {
|
||||
if x < y {
|
||||
println!("x ({x}) is smallest!");
|
||||
|
@ -8,7 +8,7 @@ Now let's use the new `Registers` struct in our driver.
|
||||
|
||||
<details>
|
||||
|
||||
- Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual
|
||||
fields without creating an intermediate reference, which would be unsound.
|
||||
- Note the use of `&raw const` / `&raw mut` to get pointers to individual fields
|
||||
without creating an intermediate reference, which would be unsound.
|
||||
|
||||
</details>
|
||||
|
@ -17,49 +17,57 @@ use log::error;
|
||||
use smccc::psci::system_off;
|
||||
use smccc::Hvc;
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
|
||||
error!("sync_exception_current");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn irq_current(_elr: u64, _spsr: u64) {
|
||||
error!("irq_current");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
|
||||
error!("fiq_current");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn serr_current(_elr: u64, _spsr: u64) {
|
||||
error!("serr_current");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
|
||||
error!("sync_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
|
||||
error!("irq_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
|
||||
error!("fiq_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
|
||||
error!("serr_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
|
@ -29,7 +29,8 @@ use smccc::Hvc;
|
||||
/// Base address of the primary PL011 UART.
|
||||
const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
|
||||
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
|
||||
// nothing else accesses that address range.
|
||||
|
@ -29,7 +29,8 @@ use smccc::Hvc;
|
||||
/// Base address of the primary PL011 UART.
|
||||
const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
|
||||
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
|
||||
// nothing else accesses that address range.
|
||||
|
@ -29,7 +29,8 @@ use smccc::Hvc;
|
||||
/// Base address of the primary PL011 UART.
|
||||
const PL011_BASE_ADDRESS: *mut u8 = 0x900_0000 as _;
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
|
||||
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
|
||||
// nothing else accesses that address range.
|
||||
|
@ -23,7 +23,8 @@ mod exceptions;
|
||||
|
||||
const PSCI_SYSTEM_OFF: u32 = 0x84000008;
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {
|
||||
// SAFETY: this only uses the declared registers and doesn't do anything
|
||||
// with memory.
|
||||
|
@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
use core::fmt::{self, Write};
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
// ANCHOR: Flags
|
||||
use bitflags::bitflags;
|
||||
@ -124,7 +123,7 @@ impl Uart {
|
||||
// of a PL011 device which is appropriately mapped.
|
||||
unsafe {
|
||||
// Write to the TX buffer.
|
||||
addr_of_mut!((*self.registers).dr).write_volatile(byte.into());
|
||||
(&raw mut (*self.registers).dr).write_volatile(byte.into());
|
||||
}
|
||||
|
||||
// Wait until the UART is no longer busy.
|
||||
@ -139,7 +138,7 @@ impl Uart {
|
||||
} else {
|
||||
// SAFETY: We know that self.registers points to the control
|
||||
// registers of a PL011 device which is appropriately mapped.
|
||||
let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };
|
||||
let data = unsafe { (&raw const (*self.registers).dr).read_volatile() };
|
||||
// TODO: Check for error conditions in bits 8-11.
|
||||
Some(data as u8)
|
||||
}
|
||||
@ -148,7 +147,7 @@ impl Uart {
|
||||
fn read_flag_register(&self) -> Flags {
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL011 device which is appropriately mapped.
|
||||
unsafe { addr_of!((*self.registers).fr).read_volatile() }
|
||||
unsafe { (&raw const (*self.registers).fr).read_volatile() }
|
||||
}
|
||||
}
|
||||
// ANCHOR_END: Uart
|
||||
|
@ -20,8 +20,8 @@ for all these functions.)
|
||||
inline assembly code, and ignore its contents afterwards. We need to use
|
||||
`inout` rather than `in` because the call could potentially clobber the
|
||||
contents of the registers.
|
||||
- This `main` function needs to be `#[no_mangle]` and `extern "C"` because it is
|
||||
called from our entry point in `entry.S`.
|
||||
- This `main` function needs to be `#[unsafe(no_mangle)]` and `extern "C"`
|
||||
because it is called from our entry point in `entry.S`.
|
||||
- `_x0`–`_x3` are the values of registers `x0`–`x3`, which are conventionally
|
||||
used by the bootloader to pass things like a pointer to the device tree.
|
||||
According to the standard aarch64 calling convention (which is what
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
- Use [`pointer::read_volatile`] and [`pointer::write_volatile`].
|
||||
- Never hold a reference.
|
||||
- Use [`addr_of!`] to get fields of structs without creating an intermediate
|
||||
- Use `&raw` to get fields of structs without creating an intermediate
|
||||
reference.
|
||||
|
||||
[`pointer::read_volatile`]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.read_volatile
|
||||
@ -19,7 +19,8 @@
|
||||
- Some existing crates for volatile access to hardware do hold references, but
|
||||
this is unsound. Whenever a reference exist, the compiler may choose to
|
||||
dereference it.
|
||||
- Use the `addr_of!` macro to get struct field pointers from a pointer to the
|
||||
struct.
|
||||
- Use `&raw` to get struct field pointers from a pointer to the struct.
|
||||
- For compatibility with old versions of Rust you can use the [`addr_of!`] macro
|
||||
instead.
|
||||
|
||||
</details>
|
||||
|
@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[link_section = ".vector_table.interrupts"]
|
||||
#[no_mangle]
|
||||
#[unsafe(link_section = ".vector_table.interrupts")]
|
||||
// SAFETY: There is no other global variable of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
pub static __INTERRUPTS: [usize; 1] = [0];
|
||||
|
@ -17,13 +17,15 @@ use log::{error, info, trace};
|
||||
use smccc::psci::system_off;
|
||||
use smccc::Hvc;
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
|
||||
error!("sync_exception_current");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn irq_current(_elr: u64, _spsr: u64) {
|
||||
trace!("irq_current");
|
||||
let intid =
|
||||
@ -31,37 +33,43 @@ extern "C" fn irq_current(_elr: u64, _spsr: u64) {
|
||||
info!("IRQ {intid:?}");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
|
||||
error!("fiq_current");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn serr_current(_elr: u64, _spsr: u64) {
|
||||
error!("serr_current");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
|
||||
error!("sync_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
|
||||
error!("irq_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
|
||||
error!("fiq_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
|
||||
error!("serr_lower");
|
||||
system_off::<Hvc>().unwrap();
|
||||
|
@ -50,7 +50,8 @@ const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;
|
||||
const PL031_IRQ: IntId = IntId::spi(2);
|
||||
|
||||
// ANCHOR: main
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
|
||||
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
|
||||
// nothing else accesses that address range.
|
||||
|
@ -15,7 +15,6 @@
|
||||
#![allow(unused)]
|
||||
|
||||
use core::fmt::{self, Write};
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
// ANCHOR: Flags
|
||||
use bitflags::bitflags;
|
||||
@ -126,7 +125,7 @@ impl Uart {
|
||||
// of a PL011 device which is appropriately mapped.
|
||||
unsafe {
|
||||
// Write to the TX buffer.
|
||||
addr_of_mut!((*self.registers).dr).write_volatile(byte.into());
|
||||
(&raw mut (*self.registers).dr).write_volatile(byte.into());
|
||||
}
|
||||
|
||||
// Wait until the UART is no longer busy.
|
||||
@ -141,7 +140,7 @@ impl Uart {
|
||||
} else {
|
||||
// SAFETY: We know that self.registers points to the control
|
||||
// registers of a PL011 device which is appropriately mapped.
|
||||
let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };
|
||||
let data = unsafe { (&raw const (*self.registers).dr).read_volatile() };
|
||||
// TODO: Check for error conditions in bits 8-11.
|
||||
Some(data as u8)
|
||||
}
|
||||
@ -150,7 +149,7 @@ impl Uart {
|
||||
fn read_flag_register(&self) -> Flags {
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL011 device which is appropriately mapped.
|
||||
unsafe { addr_of!((*self.registers).fr).read_volatile() }
|
||||
unsafe { (&raw const (*self.registers).fr).read_volatile() }
|
||||
}
|
||||
}
|
||||
// ANCHOR_END: Uart
|
||||
|
@ -13,8 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
// ANCHOR: solution
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
#[repr(C, align(4))]
|
||||
struct Registers {
|
||||
/// Data register
|
||||
@ -63,7 +61,7 @@ impl Rtc {
|
||||
pub fn read(&self) -> u32 {
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL031 device which is appropriately mapped.
|
||||
unsafe { addr_of!((*self.registers).dr).read_volatile() }
|
||||
unsafe { (&raw const (*self.registers).dr).read_volatile() }
|
||||
}
|
||||
|
||||
/// Writes a match value. When the RTC value matches this then an interrupt
|
||||
@ -71,7 +69,7 @@ impl Rtc {
|
||||
pub fn set_match(&mut self, value: u32) {
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL031 device which is appropriately mapped.
|
||||
unsafe { addr_of_mut!((*self.registers).mr).write_volatile(value) }
|
||||
unsafe { (&raw mut (*self.registers).mr).write_volatile(value) }
|
||||
}
|
||||
|
||||
/// Returns whether the match register matches the RTC value, whether or not
|
||||
@ -79,7 +77,7 @@ impl Rtc {
|
||||
pub fn matched(&self) -> bool {
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL031 device which is appropriately mapped.
|
||||
let ris = unsafe { addr_of!((*self.registers).ris).read_volatile() };
|
||||
let ris = unsafe { (&raw const (*self.registers).ris).read_volatile() };
|
||||
(ris & 0x01) != 0
|
||||
}
|
||||
|
||||
@ -90,7 +88,7 @@ impl Rtc {
|
||||
pub fn interrupt_pending(&self) -> bool {
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL031 device which is appropriately mapped.
|
||||
let ris = unsafe { addr_of!((*self.registers).mis).read_volatile() };
|
||||
let ris = unsafe { (&raw const (*self.registers).mis).read_volatile() };
|
||||
(ris & 0x01) != 0
|
||||
}
|
||||
|
||||
@ -102,14 +100,14 @@ impl Rtc {
|
||||
let imsc = if mask { 0x01 } else { 0x00 };
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL031 device which is appropriately mapped.
|
||||
unsafe { addr_of_mut!((*self.registers).imsc).write_volatile(imsc) }
|
||||
unsafe { (&raw mut (*self.registers).imsc).write_volatile(imsc) }
|
||||
}
|
||||
|
||||
/// Clears a pending interrupt, if any.
|
||||
pub fn clear_interrupt(&mut self) {
|
||||
// SAFETY: We know that self.registers points to the control registers
|
||||
// of a PL031 device which is appropriately mapped.
|
||||
unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) }
|
||||
unsafe { (&raw mut (*self.registers).icr).write_volatile(0x01) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,8 @@ In your Chromium build, add a new Rust target to `//ui/base/BUILD.gn`
|
||||
containing:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
// SAFETY: There is no other global function of this name.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn hello_from_rust() {
|
||||
println!("Hello from Rust!")
|
||||
}
|
||||
@ -32,7 +33,7 @@ subsequent exercises. If you've succeeded, you will be able to use right-click
|
||||
## Where to find help
|
||||
|
||||
- The options available to the [`rust_static_library` gn template][0]
|
||||
- Information about [`#[no_mangle]`][1]
|
||||
- Information about [`#[unsafe(no_mangle)]`][1]
|
||||
- Information about [`extern "C"`][2]
|
||||
- Information about gn's [`--export-rust-project`][3] switch
|
||||
- [How to install rust-analyzer in VSCode][4]
|
||||
@ -45,9 +46,9 @@ This example is unusual because it boils down to the lowest-common-denominator
|
||||
interop language, C. Both C++ and Rust can natively declare and call C ABI
|
||||
functions. Later in the course, we'll connect C++ directly to Rust.
|
||||
|
||||
`allow_unsafe = true` is required here because `#[no_mangle]` might allow Rust
|
||||
to generate two functions with the same name, and Rust can no longer guarantee
|
||||
that the right one is called.
|
||||
`allow_unsafe = true` is required here because `#[unsafe(no_mangle)]` might
|
||||
allow Rust to generate two functions with the same name, and Rust can no longer
|
||||
guarantee that the right one is called.
|
||||
|
||||
If you need a pure Rust executable, you can also do that using the
|
||||
`rust_executable` gn template.
|
||||
|
@ -6,7 +6,7 @@
|
||||
specifies a single function, to be called from C++, called `hello_from_rust`,
|
||||
taking no parameters and returning no value.
|
||||
- Modify your previous `hello_from_rust` function to remove `extern "C"` and
|
||||
`#[no_mangle]`. This is now just a standard Rust function.
|
||||
`#[unsafe(no_mangle)]`. This is now just a standard Rust function.
|
||||
- Modify your `gn` target to build these bindings.
|
||||
- In your C++ code, remove the forward-declaration of `hello_from_rust`.
|
||||
Instead, include the generated header file.
|
||||
|
@ -10,7 +10,7 @@ Creating pointers is safe, but dereferencing them requires `unsafe`:
|
||||
fn main() {
|
||||
let mut s = String::from("careful!");
|
||||
|
||||
let r1 = &mut s as *mut String;
|
||||
let r1 = &raw mut s;
|
||||
let r2 = r1 as *const String;
|
||||
|
||||
// SAFETY: r1 and r2 were obtained from references and so are guaranteed to
|
||||
|
@ -51,11 +51,11 @@ mod ffi {
|
||||
pub d_name: [c_char; 1024],
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn opendir(s: *const c_char) -> *mut DIR;
|
||||
unsafe extern "C" {
|
||||
pub unsafe fn opendir(s: *const c_char) -> *mut DIR;
|
||||
|
||||
#[cfg(not(all(target_os = "macos", target_arch = "x86_64")))]
|
||||
pub fn readdir(s: *mut DIR) -> *const dirent;
|
||||
pub unsafe fn readdir(s: *mut DIR) -> *const dirent;
|
||||
|
||||
// See https://github.com/rust-lang/libc/issues/414 and the section on
|
||||
// _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).
|
||||
@ -64,9 +64,9 @@ mod ffi {
|
||||
// to macOS (as opposed to iOS / wearOS / etc.) on Intel and PowerPC.
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||
#[link_name = "readdir$INODE64"]
|
||||
pub fn readdir(s: *mut DIR) -> *const dirent;
|
||||
pub unsafe fn readdir(s: *mut DIR) -> *const dirent;
|
||||
|
||||
pub fn closedir(s: *mut DIR) -> c_int;
|
||||
pub unsafe fn closedir(s: *mut DIR) -> c_int;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user