Rust如何从正在运行的程序中检索输入的argc和argv值?

我知道 Rust 应用程序初始化条目是由rustc. 我检查了compiler/rustc_codegen_ssa/src/base.rs 中的代码,它的一部分如下所示。

fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
    cx: &'a Bx::CodegenCx,
    rust_main: Bx::Value,
    rust_main_def_id: DefId,
    use_start_lang_item: bool,
) -> Bx::Function {
    // The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
    // depending on whether the target needs `argc` and `argv` to be passed in.
    let llfty = if cx.sess().target.main_needs_argc_argv {
        cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int())
    } else {
        cx.type_func(&[], cx.type_int())
    };

而且我在同一个文件中发现的东西真的很有趣,就像我下面展示的那样,从评论中,我们可以了解到 Rust 正在这个地方收集输入的 argc 和 argv,这两个参数都将在lang_start稍后传递到函数中如果我理解正确。

/// Obtain the `argc` and `argv` values to pass to the rust start function.
fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
    cx: &'a Bx::CodegenCx,
    bx: &mut Bx,
) -> (Bx::Value, Bx::Value) {
    if cx.sess().target.main_needs_argc_argv {
        // Params from native `main()` used as args for rust start function
        let param_argc = bx.get_param(0);
        let param_argv = bx.get_param(1);
        let arg_argc = bx.intcast(param_argc, cx.type_isize(), true);
        let arg_argv = param_argv;
        (arg_argc, arg_argv)
    } else {
        // The Rust start function doesn't need `argc` and `argv`, so just pass zeros.
        let arg_argc = bx.const_int(cx.type_int(), 0);
        let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p()));
        (arg_argc, arg_argv)
    }
}

但我也发现了另一个地方,它似乎与我上面在library/std/src/sys/unix/args.rs 中展示的一样。例如,如果您在 Macos 上运行 Rust 应用程序,Rust 似乎会使用两个 FFI 函数(_NSGetArgc / _NSGetArgv)来检索 argc 和 argv:

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod imp {
    use super::Args;
    use crate::ffi::CStr;

    pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}

    pub fn cleanup() {}

    #[cfg(target_os = "macos")]
    pub fn args() -> Args {
        use crate::os::unix::prelude::*;
        extern "C" {
            // These functions are in crt_externs.h.
            fn _NSGetArgc() -> *mut libc::c_int;
            fn _NSGetArgv() -> *mut *mut *mut libc::c_char;
        }

        let vec = unsafe {
            let (argc, argv) =
                (*_NSGetArgc() as isize, *_NSGetArgv() as *const *const libc::c_char);
            (0..argc as isize)
                .map(|i| {
                    let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
                    OsStringExt::from_vec(bytes)
                })
                .collect::<Vec<_>>()
        };
        Args { iter: vec.into_iter() }
    }

那么,这两个地方有什么区别呢?真正检索的东西实际上是哪个地方?

以上是Rust如何从正在运行的程序中检索输入的argc和argv值?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>