feat: add ffi c_layout
This commit is contained in:
@@ -35,6 +35,7 @@ Project or files:
|
||||
│ └── quick_error
|
||||
├── __ffi
|
||||
│ ├── c_export
|
||||
│ ├── c_layout
|
||||
│ ├── cpp
|
||||
│ ├── jni
|
||||
│ └── live-reload-rust
|
||||
@@ -136,7 +137,7 @@ Project or files:
|
||||
├── vec.rs
|
||||
└── while.rs
|
||||
|
||||
108 directories, 26 files
|
||||
109 directories, 26 files
|
||||
|
||||
```
|
||||
|
||||
|
||||
5
__ffi/c_layout/Cargo.lock
generated
Normal file
5
__ffi/c_layout/Cargo.lock
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "c_layout"
|
||||
version = "0.1.0"
|
||||
9
__ffi/c_layout/Cargo.toml
Normal file
9
__ffi/c_layout/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "c_layout"
|
||||
version = "0.1.0"
|
||||
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
5
__ffi/c_layout/README.md
Normal file
5
__ffi/c_layout/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
reference:
|
||||
https://users.rust-lang.org/t/read-into-struct/30972/3
|
||||
https://stackoverflow.com/questions/25410028/how-to-read-a-struct-from-a-file-in-rust
|
||||
|
||||
12
__ffi/c_layout/src/main.rs
Normal file
12
__ffi/c_layout/src/main.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
mod main_1;
|
||||
mod main_2;
|
||||
mod main_3;
|
||||
|
||||
fn main() {
|
||||
println!("{}", "-".repeat(88));
|
||||
main_1::run_main();
|
||||
println!("{}", "-".repeat(88));
|
||||
main_2::run_main();
|
||||
println!("{}", "-".repeat(88));
|
||||
main_3::run_main();
|
||||
}
|
||||
41
__ffi/c_layout/src/main_1.rs
Normal file
41
__ffi/c_layout/src/main_1.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use std::io::Read;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Configuration {
|
||||
item1: u8,
|
||||
item2: u16,
|
||||
item3: i32,
|
||||
item4: [char; 8],
|
||||
}
|
||||
|
||||
const CONFIG_DATA: &[u8] = &[
|
||||
0xfd, // u8
|
||||
0xb4, 0x50, // u16
|
||||
0x45, 0xcd, 0x3c, 0x15, // i32
|
||||
0x71, 0x3c, 0x87, 0xff, // char
|
||||
0xe8, 0x5d, 0x20, 0xe7, // char
|
||||
0x5f, 0x38, 0x05, 0x4a, // char
|
||||
0xc4, 0x58, 0x8f, 0xdc, // char
|
||||
0x67, 0x1d, 0xb4, 0x64, // char
|
||||
0xf2, 0xc5, 0x2c, 0x15, // char
|
||||
0xd8, 0x9a, 0xae, 0x23, // char
|
||||
0x7d, 0xce, 0x4b, 0xeb, // char
|
||||
];
|
||||
|
||||
pub fn run_main() {
|
||||
let mut buffer = CONFIG_DATA;
|
||||
|
||||
let mut config: Configuration = unsafe { mem::zeroed() };
|
||||
|
||||
let config_size = mem::size_of::<Configuration>();
|
||||
unsafe {
|
||||
let config_slice = slice::from_raw_parts_mut(&mut config as *mut _ as *mut u8, config_size);
|
||||
// `read_exact()` comes from `Read` impl for `&[u8]`
|
||||
buffer.read_exact(config_slice).unwrap();
|
||||
}
|
||||
|
||||
println!("Read structure: {:#?}", config);
|
||||
}
|
||||
80
__ffi/c_layout/src/main_2.rs
Normal file
80
__ffi/c_layout/src/main_2.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use std::io::{self, Read};
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Configuration {
|
||||
item1: u8,
|
||||
item2: u16,
|
||||
item3: i32,
|
||||
item4: [char; 8],
|
||||
}
|
||||
|
||||
const CONFIG_DATA: &[u8] = &[
|
||||
0xfd, // u8
|
||||
0xb4, 0x50, // u16
|
||||
0x45, 0xcd, 0x3c, 0x15, // i32
|
||||
0x71, 0x3c, 0x87, 0xff, // char
|
||||
0xe8, 0x5d, 0x20, 0xe7, // char
|
||||
0x5f, 0x38, 0x05, 0x4a, // char
|
||||
0xc4, 0x58, 0x8f, 0xdc, // char
|
||||
0x67, 0x1d, 0xb4, 0x64, // char
|
||||
0xf2, 0xc5, 0x2c, 0x15, // char
|
||||
0xd8, 0x9a, 0xae, 0x23, // char
|
||||
0x7d, 0xce, 0x4b, 0xeb, // char
|
||||
];
|
||||
|
||||
fn read_struct<T, R: Read>(mut read: R) -> io::Result<T> {
|
||||
let num_bytes = ::std::mem::size_of::<T>();
|
||||
unsafe {
|
||||
let mut s = mem::zeroed();//mem::uninitialized();
|
||||
let buffer = slice::from_raw_parts_mut(&mut s as *mut T as *mut u8, num_bytes);
|
||||
match read.read_exact(buffer) {
|
||||
Ok(()) => Ok(s),
|
||||
Err(e) => {
|
||||
::std::mem::forget(s);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// Here is a function that can read a struct (of a POD type) from a file:
|
||||
// fn read_structs<T, P: AsRef<std::path::Path>>(path: P) -> io::Result<Vec<T>> {
|
||||
// let path = path.as_ref();
|
||||
// let struct_size = ::std::mem::size_of::<T>();
|
||||
// let num_bytes = std::fs::metadata(path)?.len() as usize;
|
||||
// let num_structs = num_bytes / struct_size;
|
||||
// let mut reader = std::io::BufReader::new(std::fs::File::open(path)?);
|
||||
// let mut r = Vec::<T>::with_capacity(num_structs);
|
||||
// unsafe {
|
||||
// let buffer = slice::from_raw_parts_mut(r.as_mut_ptr() as *mut u8, num_bytes);
|
||||
// reader.read_exact(buffer)?;
|
||||
// r.set_len(num_structs);
|
||||
// }
|
||||
// Ok(r)
|
||||
// }
|
||||
|
||||
//// If you want to read a sequence of structs from a file, you can execute read_struct multiple times or read all the file at once:
|
||||
// fn read_structs<T, P: AsRef<std::path::Path>>(path: P) -> io::Result<Vec<T>> {
|
||||
// let path = path.as_ref();
|
||||
// let struct_size = ::std::mem::size_of::<T>();
|
||||
// let num_bytes = std::fs::metadata(path)?.len() as usize;
|
||||
// let num_structs = num_bytes / struct_size;
|
||||
// let mut reader = std::io::BufReader::new(std::fs::File::open(path)?);
|
||||
// let mut r = Vec::<T>::with_capacity(num_structs);
|
||||
// unsafe {
|
||||
// let buffer = slice::from_raw_parts_mut(r.as_mut_ptr() as *mut u8, num_bytes);
|
||||
// reader.read_exact(buffer)?;
|
||||
// r.set_len(num_structs);
|
||||
// }
|
||||
// Ok(r)
|
||||
// }
|
||||
|
||||
|
||||
pub fn run_main() {
|
||||
let c: io::Result<Configuration> = read_struct(CONFIG_DATA);
|
||||
|
||||
println!("{:#?}", c.unwrap());
|
||||
}
|
||||
43
__ffi/c_layout/src/main_3.rs
Normal file
43
__ffi/c_layout/src/main_3.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
use std::mem;
|
||||
use std::io::{Read, Write, Result};
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
struct Header {
|
||||
name: [u8; 4],
|
||||
size: u32,
|
||||
reserved: u64,
|
||||
}
|
||||
|
||||
fn parse<P: AsRef<Path>>(path: P) -> Result<()> {
|
||||
let mut file = File::open(path)?;
|
||||
|
||||
let header: Header = {
|
||||
let mut h = [0u8; mem::size_of::<Header>()];
|
||||
file.read_exact(&mut h[..])?;
|
||||
unsafe { mem::transmute(h) }
|
||||
};
|
||||
|
||||
println!("{:#?}", header);
|
||||
Ok(())
|
||||
}
|
||||
fn write<P: AsRef<Path>>(path: P, h: Header) -> Result<()> {
|
||||
let mut file = File::create(path)?;
|
||||
let bytes: [u8; mem::size_of::<Header>()] = unsafe { mem::transmute(h) };
|
||||
file.write_all(&bytes)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_main() {
|
||||
let h = Header {
|
||||
name: [1,2,3,4],
|
||||
size: 0xabcdef,
|
||||
reserved: 0x0123456789abcdef,
|
||||
};
|
||||
|
||||
write("/tmp/test.dat", h).unwrap();
|
||||
parse("/tmp/test.dat").unwrap();
|
||||
}
|
||||
Reference in New Issue
Block a user