From ff55d52d5681c44fdf0ec41cb0ee26c14c11c33f Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 3 Mar 2025 11:37:07 -0800 Subject: [PATCH 01/23] correct error type when symbol is not found --- vm/src/stdlib/ctypes/function.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 7d8dc0386a..e962fd5575 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -50,7 +50,7 @@ impl Function { library .get(terminated.as_bytes()) .map_err(|err| err.to_string()) - .map_err(|err| vm.new_value_error(err))? + .map_err(|err| vm.new_attribute_error(err))? }; let code_ptr = CodePtr(*pointer as *mut _); let return_type = match ret_type { From cd1c9e74cd1e6253a2f1f2895a09322ef6a3d1e7 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 3 Mar 2025 11:37:37 -0800 Subject: [PATCH 02/23] restype get/set --- vm/src/stdlib/ctypes/function.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index e962fd5575..a4f180415d 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -173,4 +173,14 @@ impl PyCFuncPtr { fn set_name(&self, name: String) { *self.name.write() = name; } + + #[pygetset(name = "_restype_")] + fn restype(&self) -> Option { + self._restype_.read().as_ref().cloned() + } + + #[pygetset(name = "_restype_", setter)] + fn set_restype(&self, restype: PyTypeRef) { + *self._restype_.write() = Some(restype); + } } From 47ed34b9226cb2ea0ca351d9110c092dccb6a29e Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Tue, 4 Mar 2025 11:06:42 -0800 Subject: [PATCH 03/23] tmp --- extra_tests/snippets/builtins_ctypes.py | 12 +++- vm/src/stdlib/ctypes.rs | 1 + vm/src/stdlib/ctypes/array.rs | 95 ++++++++++++++++++++++++- vm/src/stdlib/ctypes/base.rs | 21 ++++++ 4 files changed, 124 insertions(+), 5 deletions(-) diff --git a/extra_tests/snippets/builtins_ctypes.py b/extra_tests/snippets/builtins_ctypes.py index c5c563a48e..f414a26d78 100644 --- a/extra_tests/snippets/builtins_ctypes.py +++ b/extra_tests/snippets/builtins_ctypes.py @@ -33,13 +33,16 @@ def create_string_buffer(init, size=None): if size is None: size = len(init)+1 _sys.audit("ctypes.create_string_buffer", init, size) - buftype = c_char * size + buftype = c_char.__mul__(size) + print(type(c_char.__mul__(size))) + # buftype = c_char * size buf = buftype() buf.value = init return buf elif isinstance(init, int): _sys.audit("ctypes.create_string_buffer", None, init) - buftype = c_char * init + buftype = c_char.__mul__(init) + # buftype = c_char * init buf = buftype() return buf raise TypeError(init) @@ -260,8 +263,11 @@ def LoadLibrary(self, name): cdll = LibraryLoader(CDLL) +test_byte_array = create_string_buffer(b"Hello, World!") + if _os.name == "posix" or _sys.platform == "darwin": pass else: libc = cdll.msvcrt - print("rand", libc.rand()) + libc.rand() + libc.printf(test_byte_array) diff --git a/vm/src/stdlib/ctypes.rs b/vm/src/stdlib/ctypes.rs index 99866bae70..97ac527cb9 100644 --- a/vm/src/stdlib/ctypes.rs +++ b/vm/src/stdlib/ctypes.rs @@ -17,6 +17,7 @@ pub fn extend_module_nodes(vm: &VirtualMachine, module: &Py) { extend_module!(vm, module, { "_CData" => PyCData::make_class(ctx), "_SimpleCData" => PyCSimple::make_class(ctx), + "ArrayType" => array::PyCArrayType::make_class(ctx), "Array" => array::PyCArray::make_class(ctx), "CFuncPtr" => function::PyCFuncPtr::make_class(ctx), "_Pointer" => pointer::PyCPointer::make_class(ctx), diff --git a/vm/src/stdlib/ctypes/array.rs b/vm/src/stdlib/ctypes/array.rs index 8b023582c9..3384e96e57 100644 --- a/vm/src/stdlib/ctypes/array.rs +++ b/vm/src/stdlib/ctypes/array.rs @@ -1,5 +1,96 @@ +use crate::types::Callable; +use crate::{Py, PyObjectRef, PyPayload}; +use crate::{PyResult, VirtualMachine, builtins::PyTypeRef, types::Constructor}; +use crossbeam_utils::atomic::AtomicCell; +use rustpython_common::lock::PyRwLock; + +// TODO: make it metaclass +#[pyclass(name = "Array", module = "_ctypes")] +#[derive(PyPayload)] +pub struct PyCArrayType { + pub(super) inner: PyCArray, +} + +impl std::fmt::Debug for PyCArrayType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("PyCArrayType") + .field("inner", &self.inner) + .finish() + } +} + +impl Callable for PyCArrayType { + type Args = (); + fn call(zelf: &Py, _args: Self::Args, vm: &VirtualMachine) -> PyResult { + Ok(PyCArray { + typ: PyRwLock::new(zelf.inner.typ.read().clone()), + length: AtomicCell::new(zelf.inner.length.load()), + value: PyRwLock::new(zelf.inner.value.read().clone()) + } + .into_pyobject(&vm)) + } +} + +impl Constructor for PyCArrayType { + type Args = PyObjectRef; + + fn py_new(_cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult { + unreachable!() + } +} + +#[pyclass(flags(IMMUTABLETYPE))] +impl PyCArrayType {} + #[pyclass(name = "Array", module = "_ctypes")] -pub struct PyCArray {} +#[derive(PyPayload)] +pub struct PyCArray { + pub(super) typ: PyRwLock, + pub(super) length: AtomicCell, + pub(super) value: PyRwLock, +} + +impl std::fmt::Debug for PyCArray { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("PyCArray") + .field("typ", &self.typ) + .field("length", &self.length) + .finish() + } +} + +impl Constructor for PyCArray { + type Args = (PyTypeRef, usize); + + fn py_new(_cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult { + Ok(Self { + typ: PyRwLock::new(args.0), + length: AtomicCell::new(args.1), + value: PyRwLock::new(vm.ctx.none()) + } + .into_pyobject(&vm)) + } +} #[pyclass(flags(BASETYPE, IMMUTABLETYPE))] -impl PyCArray {} +impl PyCArray { + #[pygetset(name = "_type_")] + fn typ(&self) -> PyTypeRef { + self.typ.read().clone() + } + + #[pygetset(name = "_length_")] + fn length(&self) -> usize { + self.length.load() + } + + #[pygetset(name = "_value_")] + fn value(&self) -> PyObjectRef { + self.value.read().clone() + } + + #[pygetset(setter, name = "_value_")] + fn set_value(&self, value: PyObjectRef) { + *self.value.write() = value; + } +} diff --git a/vm/src/stdlib/ctypes/base.rs b/vm/src/stdlib/ctypes/base.rs index 5c5396be29..3b2be4acc0 100644 --- a/vm/src/stdlib/ctypes/base.rs +++ b/vm/src/stdlib/ctypes/base.rs @@ -1,3 +1,4 @@ +use super::array::{PyCArray, PyCArrayType}; use crate::builtins::PyType; use crate::builtins::{PyBytes, PyFloat, PyInt, PyNone, PyStr, PyTypeRef}; use crate::convert::ToPyObject; @@ -246,4 +247,24 @@ impl PyCSimple { zelf.value.store(content); Ok(()) } + + #[pyclassmethod] + fn repeat(cls: PyTypeRef, n: isize, vm: &VirtualMachine) -> PyResult { + if n < 0 { + return Err(vm.new_value_error(format!("Array length must be >= 0, not {}", n))); + } + Ok(PyCArrayType { + inner: PyCArray { + typ: PyRwLock::new(cls), + length: AtomicCell::new(n as usize), + value: PyRwLock::new(vm.ctx.none()), + }, + } + .to_pyobject(vm)) + } + + #[pyclassmethod(magic)] + fn mul(cls: PyTypeRef, n: isize, vm: &VirtualMachine) -> PyResult { + PyCSimple::repeat(cls, n, vm) + } } From ab8aa0c15383e6a06877982eb51ddb143852b87d Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Wed, 5 Mar 2025 18:56:36 -0800 Subject: [PATCH 04/23] formatting --- vm/src/stdlib/ctypes/array.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/stdlib/ctypes/array.rs b/vm/src/stdlib/ctypes/array.rs index 3384e96e57..79adef909a 100644 --- a/vm/src/stdlib/ctypes/array.rs +++ b/vm/src/stdlib/ctypes/array.rs @@ -25,7 +25,7 @@ impl Callable for PyCArrayType { Ok(PyCArray { typ: PyRwLock::new(zelf.inner.typ.read().clone()), length: AtomicCell::new(zelf.inner.length.load()), - value: PyRwLock::new(zelf.inner.value.read().clone()) + value: PyRwLock::new(zelf.inner.value.read().clone()), } .into_pyobject(&vm)) } @@ -66,7 +66,7 @@ impl Constructor for PyCArray { Ok(Self { typ: PyRwLock::new(args.0), length: AtomicCell::new(args.1), - value: PyRwLock::new(vm.ctx.none()) + value: PyRwLock::new(vm.ctx.none()), } .into_pyobject(&vm)) } From 818ad39ddba7a3792e7a7fd1d607afc9ff7d0762 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Wed, 5 Mar 2025 19:19:54 -0800 Subject: [PATCH 05/23] base of PyCSimple for PyCArray --- vm/src/stdlib/ctypes/array.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/vm/src/stdlib/ctypes/array.rs b/vm/src/stdlib/ctypes/array.rs index 79adef909a..80462ea2ee 100644 --- a/vm/src/stdlib/ctypes/array.rs +++ b/vm/src/stdlib/ctypes/array.rs @@ -3,9 +3,10 @@ use crate::{Py, PyObjectRef, PyPayload}; use crate::{PyResult, VirtualMachine, builtins::PyTypeRef, types::Constructor}; use crossbeam_utils::atomic::AtomicCell; use rustpython_common::lock::PyRwLock; +use rustpython_vm::stdlib::ctypes::base::PyCSimple; // TODO: make it metaclass -#[pyclass(name = "Array", module = "_ctypes")] +#[pyclass(name = "ArrayType", module = "_ctypes")] #[derive(PyPayload)] pub struct PyCArrayType { pub(super) inner: PyCArray, @@ -34,15 +35,15 @@ impl Callable for PyCArrayType { impl Constructor for PyCArrayType { type Args = PyObjectRef; - fn py_new(_cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult { + fn py_new(_cls: PyTypeRef, _args: Self::Args, _vm: &VirtualMachine) -> PyResult { unreachable!() } } -#[pyclass(flags(IMMUTABLETYPE))] +#[pyclass(flags(IMMUTABLETYPE), with(Callable, Constructor))] impl PyCArrayType {} -#[pyclass(name = "Array", module = "_ctypes")] +#[pyclass(name = "Array", base = "PyCSimple", module = "_ctypes")] #[derive(PyPayload)] pub struct PyCArray { pub(super) typ: PyRwLock, @@ -72,7 +73,7 @@ impl Constructor for PyCArray { } } -#[pyclass(flags(BASETYPE, IMMUTABLETYPE))] +#[pyclass(flags(BASETYPE, IMMUTABLETYPE), with(Constructor))] impl PyCArray { #[pygetset(name = "_type_")] fn typ(&self) -> PyTypeRef { @@ -84,12 +85,12 @@ impl PyCArray { self.length.load() } - #[pygetset(name = "_value_")] + #[pygetset] fn value(&self) -> PyObjectRef { self.value.read().clone() } - #[pygetset(setter, name = "_value_")] + #[pygetset(setter)] fn set_value(&self, value: PyObjectRef) { *self.value.write() = value; } From b47bbc3e2d106f70c05697e2911b391ed6f315d0 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 6 Mar 2025 19:08:57 -0800 Subject: [PATCH 06/23] more tmp --- extra_tests/snippets/builtins_ctypes.py | 1 + vm/src/stdlib/ctypes/function.rs | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/extra_tests/snippets/builtins_ctypes.py b/extra_tests/snippets/builtins_ctypes.py index f414a26d78..a55e2eff79 100644 --- a/extra_tests/snippets/builtins_ctypes.py +++ b/extra_tests/snippets/builtins_ctypes.py @@ -264,6 +264,7 @@ def LoadLibrary(self, name): cdll = LibraryLoader(CDLL) test_byte_array = create_string_buffer(b"Hello, World!") +assert test_byte_array._length_ == 14 if _os.name == "posix" or _sys.platform == "darwin": pass diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index a4f180415d..92e3fcc7d4 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -1,4 +1,5 @@ use crate::builtins::{PyStr, PyTupleRef, PyTypeRef}; +use crate::class::StaticType; use crate::convert::ToPyObject; use crate::function::FuncArgs; use crate::stdlib::ctypes::PyCData; @@ -38,13 +39,25 @@ impl Function { let args = args .iter() .map(|arg| { - if let Some(data) = arg.downcast_ref::() { - Ok(ffi_type_from_str(&data._type_).unwrap()) + dbg!(); + if arg.obj_type().is_subclass(PyCSimple::static_type().into(), vm)? { + dbg!(); + let typ = arg.get_attr("_type_", vm)?; + let typ = typ.downcast_ref::().unwrap(); + let converted = ffi_type_from_str(typ.as_str()); + match converted { + Some(t) => Ok(t), + None => Err(vm.new_type_error(format!( + "Invalid type: {}", + typ.as_str() + ))), + } } else { Err(vm.new_type_error("Expected a ctypes simple type".to_string())) } }) .collect::>>()?; + dbg!(); let terminated = format!("{}\0", function); let pointer: Symbol<'_, FP> = unsafe { library From bd5d95a2f04b8e0a143205fe6684cc8b94d85894 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sat, 8 Mar 2025 20:03:47 -0800 Subject: [PATCH 07/23] PyCSimple::to_arg --- vm/src/stdlib/ctypes/base.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/vm/src/stdlib/ctypes/base.rs b/vm/src/stdlib/ctypes/base.rs index 3b2be4acc0..7dd75f3ee2 100644 --- a/vm/src/stdlib/ctypes/base.rs +++ b/vm/src/stdlib/ctypes/base.rs @@ -268,3 +268,38 @@ impl PyCSimple { PyCSimple::repeat(cls, n, vm) } } + +impl PyCSimple { + pub fn to_arg(&self, ty: libffi::middle::Type, vm: &VirtualMachine) -> Option { + let value = unsafe { (*self.value.as_ptr()).clone() }; + if let Ok(i) = value.try_int(vm) { + let i = i.as_bigint(); + if ty.as_raw_ptr() == libffi::middle::Type::u8().as_raw_ptr() { + return i.to_u8().map(|r: u8| libffi::middle::Arg::new(&r)); + } else if ty.as_raw_ptr() == libffi::middle::Type::i8().as_raw_ptr() { + return i.to_i8().map(|r: i8| libffi::middle::Arg::new(&r)); + } else if ty.as_raw_ptr() == libffi::middle::Type::u16().as_raw_ptr() { + return i.to_u16().map(|r: u16| libffi::middle::Arg::new(&r)); + } else if ty.as_raw_ptr() == libffi::middle::Type::i16().as_raw_ptr() { + return i.to_i16().map(|r: i16| libffi::middle::Arg::new(&r)); + } else if ty.as_raw_ptr() == libffi::middle::Type::u32().as_raw_ptr() { + return i.to_u32().map(|r: u32| libffi::middle::Arg::new(&r)); + } else if ty.as_raw_ptr() == libffi::middle::Type::i32().as_raw_ptr() { + return i.to_i32().map(|r: i32| libffi::middle::Arg::new(&r)); + } else if ty.as_raw_ptr() == libffi::middle::Type::u64().as_raw_ptr() { + return i.to_u64().map(|r: u64| libffi::middle::Arg::new(&r)); + } else if ty.as_raw_ptr() == libffi::middle::Type::i64().as_raw_ptr() { + return i.to_i64().map(|r: i64| libffi::middle::Arg::new(&r)); + } else { + return None; + } + } + if let Ok(_f) = value.try_float(vm) { + todo!(); + } + if let Ok(_b) = value.try_to_bool(vm) { + todo!(); + } + None + } +} From af7083c5b24e07bcda5367043ac22a3c1d90a774 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sat, 8 Mar 2025 20:04:19 -0800 Subject: [PATCH 08/23] more snippet tests --- extra_tests/snippets/builtins_ctypes.py | 55 ++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/extra_tests/snippets/builtins_ctypes.py b/extra_tests/snippets/builtins_ctypes.py index a55e2eff79..9a626d5dd0 100644 --- a/extra_tests/snippets/builtins_ctypes.py +++ b/extra_tests/snippets/builtins_ctypes.py @@ -5,6 +5,7 @@ from _ctypes import sizeof from _ctypes import _SimpleCData from _ctypes import CFuncPtr as _CFuncPtr +import ctypes from struct import calcsize as _calcsize @@ -263,12 +264,62 @@ def LoadLibrary(self, name): cdll = LibraryLoader(CDLL) -test_byte_array = create_string_buffer(b"Hello, World!") -assert test_byte_array._length_ == 14 +test_byte_array = create_string_buffer(b"Hello, World!\n") +assert test_byte_array._length_ == 15 if _os.name == "posix" or _sys.platform == "darwin": pass else: + import os + libc = cdll.msvcrt libc.rand() + i = c_int(1) + print("start srand") + print(libc.srand(i)) + print(test_byte_array) + print(test_byte_array._type_) + print("start printf") libc.printf(test_byte_array) + + # windows pip support + + def get_win_folder_via_ctypes(csidl_name: str) -> str: + """Get folder with ctypes.""" + # There is no 'CSIDL_DOWNLOADS'. + # Use 'CSIDL_PROFILE' (40) and append the default folder 'Downloads' instead. + # https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid + + import ctypes # noqa: PLC0415 + + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + "CSIDL_PERSONAL": 5, + "CSIDL_MYPICTURES": 39, + "CSIDL_MYVIDEO": 14, + "CSIDL_MYMUSIC": 13, + "CSIDL_DOWNLOADS": 40, + "CSIDL_DESKTOPDIRECTORY": 16, + }.get(csidl_name) + if csidl_const is None: + msg = f"Unknown CSIDL name: {csidl_name}" + raise ValueError(msg) + + buf = ctypes.create_unicode_buffer(1024) + windll = getattr(ctypes, "windll") # noqa: B009 # using getattr to avoid false positive with mypy type checker + windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if it has high-bit chars. + if any(ord(c) > 255 for c in buf): # noqa: PLR2004 + buf2 = ctypes.create_unicode_buffer(1024) + if windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + if csidl_name == "CSIDL_DOWNLOADS": + return os.path.join(buf.value, "Downloads") # noqa: PTH118 + + return buf.value + + print(get_win_folder_via_ctypes("CSIDL_DOWNLOADS")) From 62259987fa87f0b33339c6b62c0445215805d477 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sat, 8 Mar 2025 20:04:32 -0800 Subject: [PATCH 09/23] par down ctypes --- Lib/ctypes/__init__.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 2e9d4c5e72..4d620b588b 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -296,7 +296,7 @@ def create_unicode_buffer(init, size=None): return buf elif isinstance(init, int): _sys.audit("ctypes.create_unicode_buffer", None, init) - buftype = c_wchar * init + buftype = c_wchar.__mul__(init) buf = buftype() return buf raise TypeError(init) @@ -495,14 +495,15 @@ def WinError(code=None, descr=None): c_ssize_t = c_longlong # functions - from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr ## void *memmove(void *, const void *, size_t); -memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr) +# TODO: RUSTPYTHON +# memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr) ## void *memset(void *, int, size_t) -memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr) +# TODO: RUSTPYTHON +# memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr) def PYFUNCTYPE(restype, *argtypes): class CFunctionType(_CFuncPtr): @@ -511,11 +512,13 @@ class CFunctionType(_CFuncPtr): _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI return CFunctionType -_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) +# TODO: RUSTPYTHON +# _cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) def cast(obj, typ): return _cast(obj, obj, typ) -_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) +# TODO: RUSTPYTHON +# _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=-1): """string_at(addr[, size]) -> string @@ -527,7 +530,8 @@ def string_at(ptr, size=-1): except ImportError: pass else: - _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) + # TODO: RUSTPYTHON + # _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) def wstring_at(ptr, size=-1): """wstring_at(addr[, size]) -> string @@ -551,8 +555,9 @@ def DllCanUnloadNow(): return 0 # S_OK return ccom.DllCanUnloadNow() -from ctypes._endian import BigEndianStructure, LittleEndianStructure -from ctypes._endian import BigEndianUnion, LittleEndianUnion +# TODO: RUSTPYTHON +# from ctypes._endian import BigEndianStructure, LittleEndianStructure +# from ctypes._endian import BigEndianUnion, LittleEndianUnion # Fill in specifically-sized types c_int8 = c_byte @@ -574,4 +579,5 @@ def DllCanUnloadNow(): else: raise SystemError(f"Unexpected sizeof(time_t): {SIZEOF_TIME_T=}") -_reset_cache() +# TODO: RUSTPYTHON +# _reset_cache() From 459699c7edcb5cc7e0156415974a5835e37325a1 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sat, 8 Mar 2025 20:04:51 -0800 Subject: [PATCH 10/23] nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS --- vm/src/stdlib/nt.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vm/src/stdlib/nt.rs b/vm/src/stdlib/nt.rs index ecc63e0aa6..48f1ab668b 100644 --- a/vm/src/stdlib/nt.rs +++ b/vm/src/stdlib/nt.rs @@ -34,6 +34,9 @@ pub(crate) mod module { #[pyattr] use libc::{O_BINARY, O_TEMPORARY}; + #[pyattr] + const _LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: i32 = 4096; + #[pyfunction] pub(super) fn access(path: OsPath, mode: u8, vm: &VirtualMachine) -> PyResult { let attr = unsafe { FileSystem::GetFileAttributesW(path.to_widecstring(vm)?.as_ptr()) }; From 503aa31f4629fc24005fd1cf21466bc56b34e8e9 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sat, 8 Mar 2025 20:06:08 -0800 Subject: [PATCH 11/23] arguments for ctypes function --- vm/src/stdlib/ctypes.rs | 67 ++++++++++++++++++++++++++++++-- vm/src/stdlib/ctypes/function.rs | 45 +++++++++++++-------- 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/vm/src/stdlib/ctypes.rs b/vm/src/stdlib/ctypes.rs index 97ac527cb9..1b52e9d9ba 100644 --- a/vm/src/stdlib/ctypes.rs +++ b/vm/src/stdlib/ctypes.rs @@ -38,7 +38,7 @@ pub(crate) mod _ctypes { use super::base::PyCSimple; use crate::builtins::PyTypeRef; use crate::class::StaticType; - use crate::function::{Either, OptionalArg}; + use crate::function::{Either, FuncArgs, OptionalArg}; use crate::stdlib::ctypes::library; use crate::{AsObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine}; use crossbeam_utils::atomic::AtomicCell; @@ -125,11 +125,12 @@ pub(crate) mod _ctypes { "d" | "g" => mem::size_of::(), "?" | "B" => mem::size_of::(), "P" | "z" | "Z" => mem::size_of::(), + "O" => mem::size_of::(), _ => unreachable!(), } } - const SIMPLE_TYPE_CHARS: &str = "cbBhHiIlLdfguzZPqQ?"; + const SIMPLE_TYPE_CHARS: &str = "cbBhHiIlLdfguzZPqQ?O"; pub fn new_simple_type( cls: Either<&PyObjectRef, &PyTypeRef>, @@ -219,9 +220,14 @@ pub(crate) mod _ctypes { #[pyfunction(name = "POINTER")] pub fn pointer(_cls: PyTypeRef) {} - #[pyfunction] + #[pyfunction(name = "pointer")] pub fn pointer_fn(_inst: PyObjectRef) {} + #[pyfunction] + fn _pointer_type_cache() -> PyObjectRef { + todo!() + } + #[cfg(target_os = "windows")] #[pyfunction(name = "_check_HRESULT")] pub fn check_hresult(_self: PyObjectRef, hr: i32, _vm: &VirtualMachine) -> PyResult { @@ -244,6 +250,24 @@ pub(crate) mod _ctypes { } } + #[pyfunction] + fn byref(_args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { + // TODO: RUSTPYTHON + return Err(vm.new_value_error("not implemented".to_string())); + } + + #[pyfunction] + fn alignment(_args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { + // TODO: RUSTPYTHON + return Err(vm.new_value_error("not implemented".to_string())); + } + + #[pyfunction] + fn resize(_args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { + // TODO: RUSTPYTHON + return Err(vm.new_value_error("not implemented".to_string())); + } + #[pyfunction] fn get_errno() -> i32 { errno::errno().0 @@ -253,4 +277,41 @@ pub(crate) mod _ctypes { fn set_errno(value: i32) { errno::set_errno(errno::Errno(value)); } + + #[cfg(windows)] + #[pyfunction] + fn get_last_error() -> PyResult { + Ok(unsafe { windows_sys::Win32::Foundation::GetLastError() }) + } + + #[cfg(windows)] + #[pyfunction] + fn set_last_error(value: u32) -> PyResult<()> { + unsafe { windows_sys::Win32::Foundation::SetLastError(value) }; + Ok(()) + } + + #[pyattr] + fn _memmove_addr(_vm: &VirtualMachine) -> usize { + let f = libc::memmove; + f as usize + } + + #[pyattr] + fn _memset_addr(_vm: &VirtualMachine) -> usize { + let f = libc::memset; + f as usize + } + + #[pyattr] + fn _string_at_addr(_vm: &VirtualMachine) -> usize { + let f = libc::strnlen; + f as usize + } + + #[pyattr] + fn _cast_addr(_vm: &VirtualMachine) -> usize { + // TODO: RUSTPYTHON + return 0; + } } diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 92e3fcc7d4..12bc0d82b0 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -1,7 +1,7 @@ use crate::builtins::{PyStr, PyTupleRef, PyTypeRef}; -use crate::class::StaticType; use crate::convert::ToPyObject; use crate::function::FuncArgs; +use crate::stdlib::ctypes::array::PyCArray; use crate::stdlib::ctypes::PyCData; use crate::stdlib::ctypes::base::{PyCSimple, ffi_type_from_str}; use crate::types::{Callable, Constructor}; @@ -17,6 +17,7 @@ use std::fmt::Debug; #[derive(Debug)] pub struct Function { + args: Vec, // TODO: no protection from use-after-free pointer: CodePtr, cif: Cif, @@ -35,21 +36,20 @@ impl Function { ret_type: &Option, vm: &VirtualMachine, ) -> PyResult { + dbg!("Start load"); // map each arg to a PyCSimple let args = args .iter() .map(|arg| { - dbg!(); - if arg.obj_type().is_subclass(PyCSimple::static_type().into(), vm)? { - dbg!(); - let typ = arg.get_attr("_type_", vm)?; - let typ = typ.downcast_ref::().unwrap(); - let converted = ffi_type_from_str(typ.as_str()); + if let Some(arg) = arg.payload_if_subclass::(vm) { + dbg!(arg); + let converted = ffi_type_from_str(&arg._type_); + dbg!(&converted); match converted { Some(t) => Ok(t), None => Err(vm.new_type_error(format!( - "Invalid type: {}", - typ.as_str() + "Invalid type" + // TODO: add type name ))), } } else { @@ -73,8 +73,10 @@ impl Function { } None => Type::c_int(), }; - let cif = Cif::new(args, return_type); + let cif = Cif::new(args.clone(), return_type); + dbg!(); Ok(Function { + args, cif, pointer: code_ptr, }) @@ -85,19 +87,30 @@ impl Function { args: Vec, vm: &VirtualMachine, ) -> PyResult { + dbg!("Start call"); let args = args .into_iter() - .map(|arg| { - if let Some(data) = arg.downcast_ref::() { - dbg!(&data); - todo!("HANDLE ARGUMENTS") - } else { - Err(vm.new_type_error("Expected a ctypes simple type".to_string())) + .enumerate() + .map(|(count, arg)| { + dbg!("Arg iter", &arg); + dbg!(&arg); + if let Some(d) = arg.payload_if_subclass::(vm) { + dbg!(d); + dbg!(&d._type_); + unsafe { + dbg!(d.value.as_ptr().as_ref().unwrap()); + } + return Ok(d.to_arg(self.args[count].clone(), vm).unwrap()); + } + if let Some(d) = arg.payload_if_subclass::(vm) { + dbg!(d); } + Err(vm.new_type_error("Expected a ctypes simple type".to_string())) }) .collect::>>()?; // TODO: FIX return type let result: i32 = unsafe { self.cif.call(self.pointer, &args) }; + dbg!("Almost end call"); Ok(vm.ctx.new_int(result).into()) } } From d9d74759e693cb0ab016e3cfd2d118d5501aafe9 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sat, 8 Mar 2025 20:06:41 -0800 Subject: [PATCH 12/23] formatting --- vm/src/stdlib/ctypes/base.rs | 6 +++++- vm/src/stdlib/ctypes/function.rs | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/vm/src/stdlib/ctypes/base.rs b/vm/src/stdlib/ctypes/base.rs index 7dd75f3ee2..d07ccba30b 100644 --- a/vm/src/stdlib/ctypes/base.rs +++ b/vm/src/stdlib/ctypes/base.rs @@ -270,7 +270,11 @@ impl PyCSimple { } impl PyCSimple { - pub fn to_arg(&self, ty: libffi::middle::Type, vm: &VirtualMachine) -> Option { + pub fn to_arg( + &self, + ty: libffi::middle::Type, + vm: &VirtualMachine, + ) -> Option { let value = unsafe { (*self.value.as_ptr()).clone() }; if let Ok(i) = value.try_int(vm) { let i = i.as_bigint(); diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 12bc0d82b0..3a79b8b3b5 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -1,8 +1,8 @@ use crate::builtins::{PyStr, PyTupleRef, PyTypeRef}; use crate::convert::ToPyObject; use crate::function::FuncArgs; -use crate::stdlib::ctypes::array::PyCArray; use crate::stdlib::ctypes::PyCData; +use crate::stdlib::ctypes::array::PyCArray; use crate::stdlib::ctypes::base::{PyCSimple, ffi_type_from_str}; use crate::types::{Callable, Constructor}; use crate::{Py, PyObjectRef, PyResult, VirtualMachine}; @@ -48,8 +48,7 @@ impl Function { match converted { Some(t) => Ok(t), None => Err(vm.new_type_error(format!( - "Invalid type" - // TODO: add type name + "Invalid type" // TODO: add type name ))), } } else { From 79282e58db1264a57e20d886e73701ee86a789a9 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sun, 9 Mar 2025 11:48:11 -0700 Subject: [PATCH 13/23] cleanup --- vm/src/stdlib/ctypes/array.rs | 10 +++++++ vm/src/stdlib/ctypes/function.rs | 47 ++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/vm/src/stdlib/ctypes/array.rs b/vm/src/stdlib/ctypes/array.rs index 80462ea2ee..c1478d621f 100644 --- a/vm/src/stdlib/ctypes/array.rs +++ b/vm/src/stdlib/ctypes/array.rs @@ -1,3 +1,4 @@ +use crate::builtins::PyBytes; use crate::types::Callable; use crate::{Py, PyObjectRef, PyPayload}; use crate::{PyResult, VirtualMachine, builtins::PyTypeRef, types::Constructor}; @@ -95,3 +96,12 @@ impl PyCArray { *self.value.write() = value; } } + +impl PyCArray { + pub fn to_arg(&self, _vm: &VirtualMachine) -> PyResult { + let value = self.value.read(); + let py_bytes = value.payload::().unwrap(); + let bytes = py_bytes.as_ref().to_vec(); + Ok(libffi::middle::Arg::new(&bytes)) + } +} diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 3a79b8b3b5..990313a3a3 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -36,27 +36,43 @@ impl Function { ret_type: &Option, vm: &VirtualMachine, ) -> PyResult { - dbg!("Start load"); // map each arg to a PyCSimple let args = args .iter() .map(|arg| { if let Some(arg) = arg.payload_if_subclass::(vm) { - dbg!(arg); let converted = ffi_type_from_str(&arg._type_); - dbg!(&converted); - match converted { + return match converted { Some(t) => Ok(t), None => Err(vm.new_type_error(format!( "Invalid type" // TODO: add type name ))), - } + }; + } + if let Some(arg) = arg.payload_if_subclass::(vm) { + let t = arg.typ.read(); + let ty_attributes = t.attributes.read(); + let ty_pystr = ty_attributes.get(vm.ctx.intern_str("_type_")).ok_or_else(|| { + vm.new_type_error("Expected a ctypes simple type".to_string()) + })?; + let ty_str = ty_pystr.downcast_ref::().ok_or_else(|| { + vm.new_type_error("Expected a ctypes simple type".to_string()) + })?.to_string(); + let converted = ffi_type_from_str(&ty_str); + return match converted { + Some(_t) => { + // TODO: Use + Ok(Type::void()) + } + None => Err(vm.new_type_error(format!( + "Invalid type" // TODO: add type name + ))), + }; } else { Err(vm.new_type_error("Expected a ctypes simple type".to_string())) } }) .collect::>>()?; - dbg!(); let terminated = format!("{}\0", function); let pointer: Symbol<'_, FP> = unsafe { library @@ -73,7 +89,6 @@ impl Function { None => Type::c_int(), }; let cif = Cif::new(args.clone(), return_type); - dbg!(); Ok(Function { args, cif, @@ -86,30 +101,26 @@ impl Function { args: Vec, vm: &VirtualMachine, ) -> PyResult { - dbg!("Start call"); let args = args .into_iter() .enumerate() .map(|(count, arg)| { - dbg!("Arg iter", &arg); - dbg!(&arg); + // none type check + if vm.is_none(&arg) { + return Ok(Arg::new(std::ptr::null())); + } if let Some(d) = arg.payload_if_subclass::(vm) { - dbg!(d); - dbg!(&d._type_); - unsafe { - dbg!(d.value.as_ptr().as_ref().unwrap()); - } return Ok(d.to_arg(self.args[count].clone(), vm).unwrap()); } if let Some(d) = arg.payload_if_subclass::(vm) { - dbg!(d); + return Ok(d.to_arg(vm).unwrap()); } Err(vm.new_type_error("Expected a ctypes simple type".to_string())) }) .collect::>>()?; - // TODO: FIX return type + dbg!(&args); + // TODO: FIX return let result: i32 = unsafe { self.cif.call(self.pointer, &args) }; - dbg!("Almost end call"); Ok(vm.ctx.new_int(result).into()) } } From b0a87f91a15b6a6194e2c76763efced9dd82b6fa Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sun, 9 Mar 2025 11:48:25 -0700 Subject: [PATCH 14/23] cleanup --- vm/src/stdlib/ctypes/function.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 990313a3a3..18dcbc65bc 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -106,9 +106,6 @@ impl Function { .enumerate() .map(|(count, arg)| { // none type check - if vm.is_none(&arg) { - return Ok(Arg::new(std::ptr::null())); - } if let Some(d) = arg.payload_if_subclass::(vm) { return Ok(d.to_arg(self.args[count].clone(), vm).unwrap()); } From 3edb1cfa1f0b53721fbe1855fc114deb9380b17f Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 13 Mar 2025 09:26:44 -0700 Subject: [PATCH 15/23] formatting --- vm/src/stdlib/ctypes/function.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 18dcbc65bc..c377bdd677 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -52,12 +52,18 @@ impl Function { if let Some(arg) = arg.payload_if_subclass::(vm) { let t = arg.typ.read(); let ty_attributes = t.attributes.read(); - let ty_pystr = ty_attributes.get(vm.ctx.intern_str("_type_")).ok_or_else(|| { - vm.new_type_error("Expected a ctypes simple type".to_string()) - })?; - let ty_str = ty_pystr.downcast_ref::().ok_or_else(|| { - vm.new_type_error("Expected a ctypes simple type".to_string()) - })?.to_string(); + let ty_pystr = + ty_attributes + .get(vm.ctx.intern_str("_type_")) + .ok_or_else(|| { + vm.new_type_error("Expected a ctypes simple type".to_string()) + })?; + let ty_str = ty_pystr + .downcast_ref::() + .ok_or_else(|| { + vm.new_type_error("Expected a ctypes simple type".to_string()) + })? + .to_string(); let converted = ffi_type_from_str(&ty_str); return match converted { Some(_t) => { From aa2fa5f6fb100052ecfb91cf3ea21ba7425658ad Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 13 Mar 2025 09:32:40 -0700 Subject: [PATCH 16/23] clippy --- vm/src/stdlib/ctypes.rs | 8 ++++---- vm/src/stdlib/ctypes/array.rs | 4 ++-- vm/src/stdlib/ctypes/function.rs | 16 +++++++--------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/vm/src/stdlib/ctypes.rs b/vm/src/stdlib/ctypes.rs index 1b52e9d9ba..b6fd150889 100644 --- a/vm/src/stdlib/ctypes.rs +++ b/vm/src/stdlib/ctypes.rs @@ -253,19 +253,19 @@ pub(crate) mod _ctypes { #[pyfunction] fn byref(_args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { // TODO: RUSTPYTHON - return Err(vm.new_value_error("not implemented".to_string())); + Err(vm.new_value_error("not implemented".to_string())) } #[pyfunction] fn alignment(_args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { // TODO: RUSTPYTHON - return Err(vm.new_value_error("not implemented".to_string())); + Err(vm.new_value_error("not implemented".to_string())) } #[pyfunction] fn resize(_args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { // TODO: RUSTPYTHON - return Err(vm.new_value_error("not implemented".to_string())); + Err(vm.new_value_error("not implemented".to_string())) } #[pyfunction] @@ -312,6 +312,6 @@ pub(crate) mod _ctypes { #[pyattr] fn _cast_addr(_vm: &VirtualMachine) -> usize { // TODO: RUSTPYTHON - return 0; + 0 } } diff --git a/vm/src/stdlib/ctypes/array.rs b/vm/src/stdlib/ctypes/array.rs index c1478d621f..44d237cd7e 100644 --- a/vm/src/stdlib/ctypes/array.rs +++ b/vm/src/stdlib/ctypes/array.rs @@ -29,7 +29,7 @@ impl Callable for PyCArrayType { length: AtomicCell::new(zelf.inner.length.load()), value: PyRwLock::new(zelf.inner.value.read().clone()), } - .into_pyobject(&vm)) + .into_pyobject(vm)) } } @@ -70,7 +70,7 @@ impl Constructor for PyCArray { length: AtomicCell::new(args.1), value: PyRwLock::new(vm.ctx.none()), } - .into_pyobject(&vm)) + .into_pyobject(vm)) } } diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index c377bdd677..41e15ac3cf 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -44,9 +44,7 @@ impl Function { let converted = ffi_type_from_str(&arg._type_); return match converted { Some(t) => Ok(t), - None => Err(vm.new_type_error(format!( - "Invalid type" // TODO: add type name - ))), + None => Err(vm.new_type_error("Invalid type".to_string())), // TODO: add type name }; } if let Some(arg) = arg.payload_if_subclass::(vm) { @@ -65,15 +63,13 @@ impl Function { })? .to_string(); let converted = ffi_type_from_str(&ty_str); - return match converted { + match converted { Some(_t) => { // TODO: Use Ok(Type::void()) } - None => Err(vm.new_type_error(format!( - "Invalid type" // TODO: add type name - ))), - }; + None => Err(vm.new_type_error("Invalid type".to_string())), // TODO: add type name + } } else { Err(vm.new_type_error("Expected a ctypes simple type".to_string())) } @@ -190,7 +186,9 @@ impl Callable for PyCFuncPtr { let name = zelf.name.read(); let res_type = zelf._restype_.read(); let func = Function::load( - inner_lib.as_ref().unwrap(), + inner_lib.as_ref().ok_or_else(|| { + vm.new_value_error("Library not found".to_string()) + })?, &name, &args.args, &res_type, From 7c19781feeccfd7747bec96548f1145fec3099f3 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 13 Mar 2025 09:39:40 -0700 Subject: [PATCH 17/23] make ctypes non-importable and fix extra dbg! --- Lib/ctypes/__init__.py | 8 +++----- vm/src/stdlib/ctypes/function.rs | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 4d620b588b..fc3a29199f 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -555,9 +555,8 @@ def DllCanUnloadNow(): return 0 # S_OK return ccom.DllCanUnloadNow() -# TODO: RUSTPYTHON -# from ctypes._endian import BigEndianStructure, LittleEndianStructure -# from ctypes._endian import BigEndianUnion, LittleEndianUnion +from ctypes._endian import BigEndianStructure, LittleEndianStructure +from ctypes._endian import BigEndianUnion, LittleEndianUnion # Fill in specifically-sized types c_int8 = c_byte @@ -579,5 +578,4 @@ def DllCanUnloadNow(): else: raise SystemError(f"Unexpected sizeof(time_t): {SIZEOF_TIME_T=}") -# TODO: RUSTPYTHON -# _reset_cache() +_reset_cache() diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 41e15ac3cf..e2255a2641 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -21,6 +21,7 @@ pub struct Function { // TODO: no protection from use-after-free pointer: CodePtr, cif: Cif, + return_ty: Type, } unsafe impl Send for Function {} @@ -95,6 +96,7 @@ impl Function { args, cif, pointer: code_ptr, + return_ty: return_type }) } @@ -117,7 +119,6 @@ impl Function { Err(vm.new_type_error("Expected a ctypes simple type".to_string())) }) .collect::>>()?; - dbg!(&args); // TODO: FIX return let result: i32 = unsafe { self.cif.call(self.pointer, &args) }; Ok(vm.ctx.new_int(result).into()) From 28c5b91630cb9b43d4bd5f5c5c008ea38ceef96f Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 13 Mar 2025 09:42:46 -0700 Subject: [PATCH 18/23] fix compile --- vm/src/stdlib/ctypes/function.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index e2255a2641..4e20594d26 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -21,7 +21,6 @@ pub struct Function { // TODO: no protection from use-after-free pointer: CodePtr, cif: Cif, - return_ty: Type, } unsafe impl Send for Function {} @@ -96,7 +95,6 @@ impl Function { args, cif, pointer: code_ptr, - return_ty: return_type }) } From f5251a509faba47d1f5ba0c9d61b2e8d825eb124 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 13 Mar 2025 09:50:09 -0700 Subject: [PATCH 19/23] formatting --- vm/src/stdlib/ctypes/function.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vm/src/stdlib/ctypes/function.rs b/vm/src/stdlib/ctypes/function.rs index 4e20594d26..c1c1230e03 100644 --- a/vm/src/stdlib/ctypes/function.rs +++ b/vm/src/stdlib/ctypes/function.rs @@ -185,9 +185,9 @@ impl Callable for PyCFuncPtr { let name = zelf.name.read(); let res_type = zelf._restype_.read(); let func = Function::load( - inner_lib.as_ref().ok_or_else(|| { - vm.new_value_error("Library not found".to_string()) - })?, + inner_lib + .as_ref() + .ok_or_else(|| vm.new_value_error("Library not found".to_string()))?, &name, &args.args, &res_type, From f0dee6ddcbf7806e5a4b7edf4a8bfd4efb10873b Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 13 Mar 2025 09:52:12 -0700 Subject: [PATCH 20/23] fix snippet --- extra_tests/snippets/builtins_ctypes.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extra_tests/snippets/builtins_ctypes.py b/extra_tests/snippets/builtins_ctypes.py index 9a626d5dd0..2108ce41a4 100644 --- a/extra_tests/snippets/builtins_ctypes.py +++ b/extra_tests/snippets/builtins_ctypes.py @@ -5,7 +5,6 @@ from _ctypes import sizeof from _ctypes import _SimpleCData from _ctypes import CFuncPtr as _CFuncPtr -import ctypes from struct import calcsize as _calcsize @@ -279,8 +278,8 @@ def LoadLibrary(self, name): print(libc.srand(i)) print(test_byte_array) print(test_byte_array._type_) - print("start printf") - libc.printf(test_byte_array) + # print("start printf") + # libc.printf(test_byte_array) # windows pip support @@ -322,4 +321,4 @@ def get_win_folder_via_ctypes(csidl_name: str) -> str: return buf.value - print(get_win_folder_via_ctypes("CSIDL_DOWNLOADS")) + # print(get_win_folder_via_ctypes("CSIDL_DOWNLOADS")) From 7405f28630f073d6400b1524f555135e103cb3ec Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sun, 23 Mar 2025 17:40:58 -0700 Subject: [PATCH 21/23] force failure to import ctypes --- Lib/ctypes/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index fc3a29199f..8a75aa6356 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -36,6 +36,9 @@ FUNCFLAG_USE_ERRNO as _FUNCFLAG_USE_ERRNO, \ FUNCFLAG_USE_LASTERROR as _FUNCFLAG_USE_LASTERROR +# TODO: RUSTPYTHON remove this +from _ctypes import _non_existing_function + # WINOLEAPI -> HRESULT # WINOLEAPI_(type) # From 86e778e9fe00b034227ab66988f064a56667e741 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sun, 23 Mar 2025 22:02:14 -0700 Subject: [PATCH 22/23] Update Lib/ctypes/__init__.py Co-authored-by: Jeong, YunWon <69878+youknowone@users.noreply.github.com> --- Lib/ctypes/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 8a75aa6356..8023f4651d 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -299,6 +299,8 @@ def create_unicode_buffer(init, size=None): return buf elif isinstance(init, int): _sys.audit("ctypes.create_unicode_buffer", None, init) + # XXX: RustPython + # buftype = c_wchar * init buftype = c_wchar.__mul__(init) buf = buftype() return buf From 71066c980fc2e37c1ca5062a6e029d04cfa17aa7 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" <69878+youknowone@users.noreply.github.com> Date: Tue, 25 Mar 2025 09:08:19 +0900 Subject: [PATCH 23/23] Replace comment marker --- Lib/ctypes/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 8023f4651d..b8b005061f 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -299,7 +299,7 @@ def create_unicode_buffer(init, size=None): return buf elif isinstance(init, int): _sys.audit("ctypes.create_unicode_buffer", None, init) - # XXX: RustPython + # XXX: RUSTPYTHON # buftype = c_wchar * init buftype = c_wchar.__mul__(init) buf = buftype() @@ -503,11 +503,11 @@ def WinError(code=None, descr=None): from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr ## void *memmove(void *, const void *, size_t); -# TODO: RUSTPYTHON +# XXX: RUSTPYTHON # memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr) ## void *memset(void *, int, size_t) -# TODO: RUSTPYTHON +# XXX: RUSTPYTHON # memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr) def PYFUNCTYPE(restype, *argtypes): @@ -517,12 +517,12 @@ class CFunctionType(_CFuncPtr): _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI return CFunctionType -# TODO: RUSTPYTHON +# XXX: RUSTPYTHON # _cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) def cast(obj, typ): return _cast(obj, obj, typ) -# TODO: RUSTPYTHON +# XXX: RUSTPYTHON # _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=-1): """string_at(addr[, size]) -> string @@ -535,7 +535,7 @@ def string_at(ptr, size=-1): except ImportError: pass else: - # TODO: RUSTPYTHON + # XXX: RUSTPYTHON # _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) def wstring_at(ptr, size=-1): """wstring_at(addr[, size]) -> string