From 2baeb3e882ad81448e6f4e173f1374e4398626ab Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 27 Feb 2025 20:22:09 -0800 Subject: [PATCH 1/4] _ctypes.addressof Signed-off-by: Ashwin Naren --- vm/src/stdlib/ctypes.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vm/src/stdlib/ctypes.rs b/vm/src/stdlib/ctypes.rs index 2580939b62..701094a375 100644 --- a/vm/src/stdlib/ctypes.rs +++ b/vm/src/stdlib/ctypes.rs @@ -214,6 +214,16 @@ pub(crate) mod _ctypes { } } + #[pyfunction] + fn addressof(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { + if obj.is_instance(PyCSimple::static_type().as_ref(), vm)? { + let simple = obj.downcast_ref::().unwrap(); + Ok(simple.value.as_ptr() as usize) + } else { + Err(vm.new_type_error("expected a ctypes instance".to_string())) + } + } + #[pyfunction] fn get_errno() -> i32 { errno::errno().0 From 66c40c6616e7157b0f6c972d24f3cd18e3a25ce4 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 27 Feb 2025 20:56:20 -0800 Subject: [PATCH 2/4] ctypes.Structure implementation Signed-off-by: Ashwin Naren --- vm/src/stdlib/ctypes/structure.rs | 54 ++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/vm/src/stdlib/ctypes/structure.rs b/vm/src/stdlib/ctypes/structure.rs index 13cca6c260..d5b2058323 100644 --- a/vm/src/stdlib/ctypes/structure.rs +++ b/vm/src/stdlib/ctypes/structure.rs @@ -1,5 +1,57 @@ +use std::collections::HashMap; +use crate::builtins::{PyList, PyStr, PyTuple, PyTypeRef}; +use crate::function::FuncArgs; +use crate::{AsObject, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine}; +use rustpython_vm::types::Constructor; +use std::fmt::Debug; +use rustpython_common::lock::PyRwLock; +use crate::types::GetAttr; + #[pyclass(name = "Structure", module = "_ctypes")] -pub struct PyCStructure {} +#[derive(PyPayload, Debug)] +pub struct PyCStructure { + field_data: PyRwLock>, + data: PyRwLock> +} + +impl Constructor for PyCStructure { + type Args = FuncArgs; + + fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { + let fields_attr = cls.get_class_attr(vm.ctx.interned_str("_fields_").unwrap()).ok_or_else(|| { + vm.new_attribute_error("Structure must have a _fields_ attribute".to_string()) + })?; + // downcast into list + let fields = fields_attr.downcast_ref::().ok_or_else(|| { + vm.new_type_error("Structure _fields_ attribute must be a list".to_string()) + })?; + let fields = fields.borrow_vec(); + let mut field_data = HashMap::new(); + for field in fields.iter() { + let field = field.downcast_ref::().ok_or_else(|| { + vm.new_type_error("Field must be a tuple".to_string()) + })?; + let name = field.get(0).unwrap().downcast_ref::().ok_or_else(|| { + vm.new_type_error("Field name must be a string".to_string()) + })?; + let typ = field.get(1).unwrap().clone(); + field_data.insert(name.as_str().to_string(), typ); + } + todo!("Implement PyCStructure::py_new") + } +} + +impl GetAttr for PyCStructure { + fn getattro(zelf: &Py, name: &Py, vm: &VirtualMachine) -> PyResult { + let name = name.to_string(); + let data = zelf.data.read(); + match data.get(&name) { + Some(value) => Ok(value.clone()), + None => Err(vm.new_attribute_error(format!("No attribute named {}", name))) + } + } +} #[pyclass(flags(BASETYPE, IMMUTABLETYPE))] impl PyCStructure {} + From 2c6e126498cb063d0aa47c441245b135f04bc251 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 27 Feb 2025 20:56:43 -0800 Subject: [PATCH 3/4] clippy fix Signed-off-by: Ashwin Naren --- vm/src/stdlib/ctypes/structure.rs | 34 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/vm/src/stdlib/ctypes/structure.rs b/vm/src/stdlib/ctypes/structure.rs index d5b2058323..6404700a42 100644 --- a/vm/src/stdlib/ctypes/structure.rs +++ b/vm/src/stdlib/ctypes/structure.rs @@ -1,26 +1,29 @@ -use std::collections::HashMap; use crate::builtins::{PyList, PyStr, PyTuple, PyTypeRef}; use crate::function::FuncArgs; +use crate::types::GetAttr; use crate::{AsObject, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine}; +use rustpython_common::lock::PyRwLock; use rustpython_vm::types::Constructor; +use std::collections::HashMap; use std::fmt::Debug; -use rustpython_common::lock::PyRwLock; -use crate::types::GetAttr; #[pyclass(name = "Structure", module = "_ctypes")] #[derive(PyPayload, Debug)] pub struct PyCStructure { + #[allow(dead_code)] field_data: PyRwLock>, - data: PyRwLock> + data: PyRwLock>, } impl Constructor for PyCStructure { type Args = FuncArgs; fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { - let fields_attr = cls.get_class_attr(vm.ctx.interned_str("_fields_").unwrap()).ok_or_else(|| { - vm.new_attribute_error("Structure must have a _fields_ attribute".to_string()) - })?; + let fields_attr = cls + .get_class_attr(vm.ctx.interned_str("_fields_").unwrap()) + .ok_or_else(|| { + vm.new_attribute_error("Structure must have a _fields_ attribute".to_string()) + })?; // downcast into list let fields = fields_attr.downcast_ref::().ok_or_else(|| { vm.new_type_error("Structure _fields_ attribute must be a list".to_string()) @@ -28,12 +31,14 @@ impl Constructor for PyCStructure { let fields = fields.borrow_vec(); let mut field_data = HashMap::new(); for field in fields.iter() { - let field = field.downcast_ref::().ok_or_else(|| { - vm.new_type_error("Field must be a tuple".to_string()) - })?; - let name = field.get(0).unwrap().downcast_ref::().ok_or_else(|| { - vm.new_type_error("Field name must be a string".to_string()) - })?; + let field = field + .downcast_ref::() + .ok_or_else(|| vm.new_type_error("Field must be a tuple".to_string()))?; + let name = field + .get(0) + .unwrap() + .downcast_ref::() + .ok_or_else(|| vm.new_type_error("Field name must be a string".to_string()))?; let typ = field.get(1).unwrap().clone(); field_data.insert(name.as_str().to_string(), typ); } @@ -47,11 +52,10 @@ impl GetAttr for PyCStructure { let data = zelf.data.read(); match data.get(&name) { Some(value) => Ok(value.clone()), - None => Err(vm.new_attribute_error(format!("No attribute named {}", name))) + None => Err(vm.new_attribute_error(format!("No attribute named {}", name))), } } } #[pyclass(flags(BASETYPE, IMMUTABLETYPE))] impl PyCStructure {} - From 19505b5545b6f07b990f94f780dabdf44af28a6b Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Thu, 27 Feb 2025 21:13:13 -0800 Subject: [PATCH 4/4] formatting Signed-off-by: Ashwin Naren --- vm/src/stdlib/ctypes/structure.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/stdlib/ctypes/structure.rs b/vm/src/stdlib/ctypes/structure.rs index 6404700a42..c6cf158953 100644 --- a/vm/src/stdlib/ctypes/structure.rs +++ b/vm/src/stdlib/ctypes/structure.rs @@ -35,7 +35,7 @@ impl Constructor for PyCStructure { .downcast_ref::() .ok_or_else(|| vm.new_type_error("Field must be a tuple".to_string()))?; let name = field - .get(0) + .first() .unwrap() .downcast_ref::() .ok_or_else(|| vm.new_type_error("Field name must be a string".to_string()))?;