diff --git a/crates/oaknode/src/nodes/timeformat.rs b/crates/oaknode/src/nodes/timeformat.rs index a048c8765..afc28daf7 100644 --- a/crates/oaknode/src/nodes/timeformat.rs +++ b/crates/oaknode/src/nodes/timeformat.rs @@ -67,11 +67,18 @@ struct Tm { // `localtime_r` / `gmtime_r` (C `time.h`). Declared locally instead of // pulling in a libc crate; both symbols live in the platform C library -// that `std` already links. +// that `std` already links. Windows (UCRT) has the `_s` variants with +// reversed argument order and a 64-bit time_t. +#[cfg(not(target_os = "windows"))] extern "C" { fn localtime_r(timep: *const c_long, result: *mut Tm) -> *mut Tm; fn gmtime_r(timep: *const c_long, result: *mut Tm) -> *mut Tm; } +#[cfg(target_os = "windows")] +extern "C" { + fn localtime_s(result: *mut Tm, timep: *const i64) -> i32; + fn gmtime_s(result: *mut Tm, timep: *const i64) -> i32; +} /// Expand Qt date/time format tokens (`QDateTime::toString` syntax): /// the field tokens d/dd, M/MM, yy/yyyy, h/hh, H/HH, m/mm, s/ss, z/zz/zzz, @@ -287,6 +294,7 @@ impl NodeBehavior for TimeFormatNode { let ms = (ms_since_epoch % 1000) as i32; let mut tm: Tm = unsafe { std::mem::zeroed() }; + #[cfg(not(target_os = "windows"))] unsafe { if to_bool(&local_val) { localtime_r(&secs, &mut tm); @@ -294,6 +302,15 @@ impl NodeBehavior for TimeFormatNode { gmtime_r(&secs, &mut tm); } } + #[cfg(target_os = "windows")] + unsafe { + let secs64 = secs as i64; + if to_bool(&local_val) { + localtime_s(&mut tm, &secs64); + } else { + gmtime_s(&mut tm, &secs64); + } + } let output = format_date_time(&tm, ms, &to_text(&format_val)); table.push(crate::value::ValueType::Text, NodeValue::Text(output), None); diff --git a/crates/oakplugin/tests/suites_test.rs b/crates/oakplugin/tests/suites_test.rs index 44994e8ec..c94c51fd3 100644 --- a/crates/oakplugin/tests/suites_test.rs +++ b/crates/oakplugin/tests/suites_test.rs @@ -743,14 +743,16 @@ fn multithread_suite_spawned_callbacks() { assert_eq!((s.multi_thread)(counter_worker, 8, raw as *mut c_void), OK); } for i in 0..8 { - let name = Box::leak(format!("ctr{i}").into_boxed_str()); + // C 侧按 NUL 结尾读名字——必须经 cs() 包成 CString(裸 + // `str::as_ptr()` 不带 NUL,CStr::from_ptr 会读越界)。 + let name = cs(&format!("ctr{i}")); let mut v = 0; - // 注意 `&*set`(Arc 负载)而非 `&set`(Arc 结构体)。 + // 注意传 `&*set`(Arc 负载)而非 `&set`(Arc 结构体)。 unsafe { assert_eq!( (ps.get_int)( &*set as *const _ as *mut c_void, - name.as_ptr() as *const c_char, + name.as_ptr(), 0, &mut v ), diff --git a/tooling/ffmpeg/build-ffmpeg.sh b/tooling/ffmpeg/build-ffmpeg.sh index 994ca79e5..5827e62da 100755 --- a/tooling/ffmpeg/build-ffmpeg.sh +++ b/tooling/ffmpeg/build-ffmpeg.sh @@ -139,12 +139,12 @@ if [ -d /opt/homebrew/lib/pkgconfig/openjpeg ]; then fi enable_if_pkg libopenjp2 libopenjpeg # openh264 is redundant for us (decode: FFmpeg's native h264; encode: -# x264) and its MinGW package does not satisfy the static link — skip it -# on Windows. +# x264) and snappy only feeds the hap encoder; neither MinGW package +# satisfies the static link — skip both on Windows. if [ -z "${MSYSTEM:-}" ]; then enable_if_pkg openh264 libopenh264 + enable_if_pkg snappy libsnappy fi -enable_if_pkg snappy libsnappy enable_if_pkg wavpack libwavpack enable_if_pkg webp libwebp enable_if_pkg xvid libxvid