|
8 | 8 | // Imports |
9 | 9 | // ============================================================================ |
10 | 10 |
|
11 | | -use core::sync::atomic::{AtomicPtr, Ordering}; |
| 11 | +use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; |
12 | 12 |
|
13 | 13 | pub use neotron_ffi::{FfiBuffer, FfiByteSlice, FfiString}; |
14 | 14 |
|
@@ -46,14 +46,20 @@ extern "C" { |
46 | 46 | /// Once you've hit the application `main()`, this will be non-null. |
47 | 47 | static API: AtomicPtr<Api> = AtomicPtr::new(core::ptr::null_mut()); |
48 | 48 |
|
| 49 | +/// Number of arguments passed |
| 50 | +static ARG_COUNT: AtomicUsize = AtomicUsize::new(0); |
| 51 | + |
| 52 | +/// Start of the argument list |
| 53 | +static ARG_PTR: AtomicPtr<FfiString> = AtomicPtr::new(core::ptr::null_mut()); |
| 54 | + |
49 | 55 | // ============================================================================ |
50 | 56 | // Types |
51 | 57 | // ============================================================================ |
52 | 58 |
|
53 | 59 | /// The type of the application entry-point. |
54 | 60 | /// |
55 | 61 | /// The OS calls a function of this type. |
56 | | -pub type AppStartFn = extern "C" fn(*mut crate::Api) -> i32; |
| 62 | +pub use neotron_api::AppStartFn; |
57 | 63 |
|
58 | 64 | /// The result type for any SDK function. |
59 | 65 | /// |
@@ -259,11 +265,39 @@ impl Drop for ReadDir { |
259 | 265 | /// Will jump to the application entry point, and `extern "C"` function |
260 | 266 | /// called `main`. |
261 | 267 | #[no_mangle] |
262 | | -extern "C" fn app_entry(api: *mut Api) -> i32 { |
263 | | - API.store(api, Ordering::Relaxed); |
| 268 | +extern "C" fn app_entry(api: *const Api, argc: usize, argv: *const FfiString) -> i32 { |
| 269 | + let _check: AppStartFn = app_entry; |
| 270 | + API.store(api as *mut Api, Ordering::Relaxed); |
| 271 | + ARG_COUNT.store(argc, Ordering::Relaxed); |
| 272 | + ARG_PTR.store(argv as *mut FfiString, Ordering::Relaxed); |
264 | 273 | unsafe { neotron_main() } |
265 | 274 | } |
266 | 275 |
|
| 276 | +/// Get a command line argument. |
| 277 | +/// |
| 278 | +/// Given an zero-based index, returns `Some(str)` if that argument was |
| 279 | +/// provided, otherwise None. |
| 280 | +/// |
| 281 | +/// Does not return the name of the program in the first argument. |
| 282 | +#[cfg(target_os = "none")] |
| 283 | +pub fn arg(n: usize) -> Option<&'static str> { |
| 284 | + let arg_count = ARG_COUNT.load(Ordering::Relaxed); |
| 285 | + let arg_ptr = ARG_PTR.load(Ordering::Relaxed); |
| 286 | + let arg_slice = unsafe { core::slice::from_raw_parts(arg_ptr, arg_count) }; |
| 287 | + arg_slice.get(n).map(|ffi| ffi.as_str()) |
| 288 | +} |
| 289 | + |
| 290 | +/// Get a command line argument. |
| 291 | +/// |
| 292 | +/// Given an zero-based index, returns `Some(str)` if that argument was |
| 293 | +/// provided, otherwise None. |
| 294 | +/// |
| 295 | +/// Does not return the name of the program in the first argument. |
| 296 | +#[cfg(not(target_os = "none"))] |
| 297 | +pub fn arg(n: usize) -> Option<String> { |
| 298 | + std::env::args().skip(1).nth(n) |
| 299 | +} |
| 300 | + |
267 | 301 | /// Get information about a file on disk. |
268 | 302 | pub fn stat(_path: path::Path) -> Result<api::file::Stat> { |
269 | 303 | todo!() |
|
0 commit comments