Given a main function that is declared as so
fn main(_argc: i32, _argv: *const *const u8) -> i32
How do you actually convert the *const *const u8
value into something we can operate with in Rust?
My working code thus far is
#![feature(start)]
#![no_std]
#![no_main]
extern crate libc;
mod io;
use core::slice::from_raw_parts;
use core::mem::size_of_val;
#[no_mangle]
pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
for argument in from_raw_parts(_argv, _argc as usize) {
for character in from_raw_parts(argument, size_of_val(argument)) {
io::print_char(*character as i8)
}
}
io::print_char(b'\n' as i8);
for character in "World, Hello".bytes() {
io::print_char(character as i8);
}
io::print_char(b'\n' as i8);
}
0
}
However, running the application with World, Hello
results in the arguments getting printed out mangled, whereas the byte slice created in memory prints fine.
���������t���t
World, Hello
1 Like
This code is missing the io
module.
It's just a wrapper over putchar
extern crate libc;
extern {
pub fn putchar(c: i8) -> i8;
}
pub fn print_char(input: i8) {
unsafe { let _ = putchar(input); }
}
Try something like this:
#[no_mangle]
pub extern fn main(_argc: i32, _argv: *const *const libc::c_char) -> i32 {
unsafe {
for argument in from_raw_parts(_argv, _argc as usize) {
for character in from_raw_parts(*argument, libc::strlen(*argument)) {
io::print_char(*character)
}
}
}
0
}
Note that the outer for loop does not read memory; the type of "argument" is &*const libc::c_char
, which is essentially the same type as argv.
2 Likes
How about this: Rust Playground?
for &arg in slice::from_raw_parts(_argv, _argc as usize) {
let slice = slice::from_raw_parts(arg, strlen(arg));
let s: &str = str::from_utf8_unchecked(slice);
print_ln(s).unwrap();
}
So that works. I am able to properly read the arguments and print them with the following:
#![feature(start)]
#![no_std]
#![no_main]
extern crate libc;
mod io;
use core::slice::from_raw_parts;
#[no_mangle]
pub extern fn main(_argc: i32, _argv: *const *const i8) -> i32 {
unsafe {
for &argument in from_raw_parts(_argv, _argc as usize) {
let capacity = libc::strlen(argument);
for &character in from_raw_parts(argument, capacity) {
io::print_char(character);
}
io::print_char(b' ' as i8);
}
io::print_char(b'\n' as i8);
}
0
}