Skip to content

Commit 2fb1e85

Browse files
committed
Add the msvcrt stdlib module
1 parent 199c75b commit 2fb1e85

3 files changed

Lines changed: 78 additions & 10 deletions

File tree

‎vm/src/stdlib/mod.rs‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use crate::pyobject::PyObjectRef;
2+
use crate::vm::VirtualMachine;
3+
use std::collections::HashMap;
4+
15
pub mod array;
26
#[cfg(feature = "rustpython-parser")]
37
pub(crate) mod ast;
@@ -33,15 +37,17 @@ mod tokenize;
3337
mod unicodedata;
3438
mod warnings;
3539
mod weakref;
36-
use std::collections::HashMap;
3740

38-
use crate::vm::VirtualMachine;
41+
#[cfg(not(target_arch = "wasm32"))]
42+
#[macro_use]
43+
mod os;
44+
3945
#[cfg(not(target_arch = "wasm32"))]
4046
mod faulthandler;
47+
#[cfg(windows)]
48+
mod msvcrt;
4149
#[cfg(not(target_arch = "wasm32"))]
4250
mod multiprocessing;
43-
#[cfg(not(target_arch = "wasm32"))]
44-
mod os;
4551
#[cfg(all(unix, not(any(target_os = "android", target_os = "redox"))))]
4652
mod pwd;
4753
#[cfg(not(target_arch = "wasm32"))]
@@ -57,8 +63,6 @@ mod winreg;
5763
#[cfg(not(target_arch = "wasm32"))]
5864
mod zlib;
5965

60-
use crate::pyobject::PyObjectRef;
61-
6266
pub type StdlibInitFunc = Box<dyn Fn(&VirtualMachine) -> PyObjectRef>;
6367

6468
pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
@@ -136,6 +140,7 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
136140
// Windows-only
137141
#[cfg(windows)]
138142
{
143+
modules.insert("msvcrt".to_owned(), Box::new(msvcrt::make_module));
139144
modules.insert("_winapi".to_owned(), Box::new(winapi::make_module));
140145
modules.insert("winreg".to_owned(), Box::new(winreg::make_module));
141146
}

‎vm/src/stdlib/msvcrt.rs‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use crate::obj::objbytes::PyBytesRef;
2+
use crate::obj::objstr::PyStringRef;
3+
use crate::pyobject::{PyObjectRef, PyResult};
4+
use crate::VirtualMachine;
5+
6+
use itertools::Itertools;
7+
8+
extern "C" {
9+
fn _getch() -> i32;
10+
fn _getwch() -> u32;
11+
fn _getche() -> i32;
12+
fn _getwche() -> u32;
13+
fn _putch(c: u32) -> i32;
14+
fn _putwch(c: u16) -> u32;
15+
}
16+
17+
fn msvcrt_getch() -> Vec<u8> {
18+
let c = unsafe { _getch() };
19+
vec![c as u8]
20+
}
21+
fn msvcrt_getwch() -> String {
22+
let c = unsafe { _getwch() };
23+
std::char::from_u32(c).unwrap().to_string()
24+
}
25+
fn msvcrt_getche() -> Vec<u8> {
26+
let c = unsafe { _getche() };
27+
vec![c as u8]
28+
}
29+
fn msvcrt_getwche() -> String {
30+
let c = unsafe { _getwche() };
31+
std::char::from_u32(c).unwrap().to_string()
32+
}
33+
fn msvcrt_putch(b: PyBytesRef, vm: &VirtualMachine) -> PyResult<()> {
34+
let &c = b.get_value().iter().exactly_one().map_err(|_| {
35+
vm.new_type_error("putch() argument must be a byte string of length 1".to_owned())
36+
})?;
37+
unsafe { suppress_iph!(_putch(c.into())) };
38+
Ok(())
39+
}
40+
fn msvcrt_putwch(s: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
41+
let c = s.as_str().chars().exactly_one().map_err(|_| {
42+
vm.new_type_error("putch() argument must be a string of length 1".to_owned())
43+
})?;
44+
unsafe { suppress_iph!(_putwch(c as u16)) };
45+
Ok(())
46+
}
47+
48+
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
49+
let ctx = &vm.ctx;
50+
py_module!(vm, "_msvcrt", {
51+
"getch" => ctx.new_function(msvcrt_getch),
52+
"getwch" => ctx.new_function(msvcrt_getwch),
53+
"getche" => ctx.new_function(msvcrt_getche),
54+
"getwche" => ctx.new_function(msvcrt_getwche),
55+
"putch" => ctx.new_function(msvcrt_putch),
56+
"putwch" => ctx.new_function(msvcrt_putwch),
57+
})
58+
}

‎vm/src/stdlib/os.rs‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,13 +1211,15 @@ type InvalidParamHandler = extern "C" fn(
12111211
);
12121212
#[cfg(windows)]
12131213
extern "C" {
1214-
fn _set_thread_local_invalid_parameter_handler(
1214+
#[doc(hidden)]
1215+
pub fn _set_thread_local_invalid_parameter_handler(
12151216
pNew: InvalidParamHandler,
12161217
) -> InvalidParamHandler;
12171218
}
12181219

12191220
#[cfg(windows)]
1220-
extern "C" fn silent_iph_handler(
1221+
#[doc(hidden)]
1222+
pub extern "C" fn silent_iph_handler(
12211223
_: *const libc::wchar_t,
12221224
_: *const libc::wchar_t,
12231225
_: *const libc::wchar_t,
@@ -1226,13 +1228,16 @@ extern "C" fn silent_iph_handler(
12261228
) {
12271229
}
12281230

1231+
#[macro_export]
12291232
macro_rules! suppress_iph {
12301233
($e:expr) => {{
12311234
#[cfg(windows)]
12321235
{
1233-
let old = _set_thread_local_invalid_parameter_handler(silent_iph_handler);
1236+
let old = $crate::stdlib::os::_set_thread_local_invalid_parameter_handler(
1237+
$crate::stdlib::os::silent_iph_handler,
1238+
);
12341239
let ret = $e;
1235-
_set_thread_local_invalid_parameter_handler(old);
1240+
$crate::stdlib::os::_set_thread_local_invalid_parameter_handler(old);
12361241
ret
12371242
}
12381243
#[cfg(not(windows))]

0 commit comments

Comments
 (0)