作者:书友53537817 | 来源:互联网 | 2023-06-08 08:10
我知道 Rust 应用程序初始化条目是由rustc. 我检查了compiler/rustc_codegen_ssa/src/base.rs 中的代码,它的一部分如下所示。fn create_entry
我知道 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::>()
};
Args { iter: vec.into_iter() }
}
那么,这两个地方有什么区别呢?真正检索的东西实际上是哪个地方?