Skip to content

Commit 9528ee8

Browse files
authored
Merge pull request #5653 from arihant2math/ctypes-pt5
_ctypes pt. 5
2 parents 0e6e256 + 8af105f commit 9528ee8

File tree

8 files changed

+466
-166
lines changed

8 files changed

+466
-166
lines changed

crates/vm/src/stdlib/ctypes.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
pub(crate) mod array;
44
pub(crate) mod base;
5+
pub(crate) mod field;
56
pub(crate) mod function;
67
pub(crate) mod library;
78
pub(crate) mod pointer;
89
pub(crate) mod structure;
10+
pub(crate) mod thunk;
911
pub(crate) mod union;
1012

1113
use crate::builtins::PyModule;
@@ -17,14 +19,18 @@ pub fn extend_module_nodes(vm: &VirtualMachine, module: &Py<PyModule>) {
1719
let ctx = &vm.ctx;
1820
PyCSimpleType::make_class(ctx);
1921
array::PyCArrayType::make_class(ctx);
22+
field::PyCFieldType::make_class(ctx);
23+
pointer::PyCPointerType::make_class(ctx);
2024
extend_module!(vm, module, {
2125
"_CData" => PyCData::make_class(ctx),
2226
"_SimpleCData" => PyCSimple::make_class(ctx),
2327
"Array" => array::PyCArray::make_class(ctx),
28+
"CField" => field::PyCField::make_class(ctx),
2429
"CFuncPtr" => function::PyCFuncPtr::make_class(ctx),
2530
"_Pointer" => pointer::PyCPointer::make_class(ctx),
2631
"_pointer_type_cache" => ctx.new_dict(),
2732
"Structure" => structure::PyCStructure::make_class(ctx),
33+
"CThunkObject" => thunk::PyCThunk::make_class(ctx),
2834
"Union" => union::PyCUnion::make_class(ctx),
2935
})
3036
}
@@ -207,7 +213,9 @@ pub(crate) mod _ctypes {
207213
// TODO: load_flags
208214
let cache = library::libcache();
209215
let mut cache_write = cache.write();
210-
let (id, _) = cache_write.get_or_insert_lib(&name, vm).unwrap();
216+
let (id, _) = cache_write
217+
.get_or_insert_lib(&name, vm)
218+
.map_err(|e| vm.new_os_error(e.to_string()))?;
211219
Ok(id)
212220
}
213221

crates/vm/src/stdlib/ctypes/array.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ impl PyCArray {
106106
}
107107

108108
impl PyCArray {
109+
#[allow(unused)]
109110
pub fn to_arg(&self, _vm: &VirtualMachine) -> PyResult<libffi::middle::Arg> {
110111
let value = self.value.read();
111112
let py_bytes = value.downcast_ref::<PyBytes>().unwrap();

crates/vm/src/stdlib/ctypes/base.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,12 @@ impl Constructor for PyCSimple {
218218
_ => vm.ctx.none(), // "z" | "Z" | "P"
219219
}
220220
};
221-
Ok(PyCSimple {
221+
PyCSimple {
222222
_type_,
223223
value: AtomicCell::new(value),
224224
}
225-
.to_pyobject(vm))
225+
.into_ref_with_type(vm, cls)
226+
.map(Into::into)
226227
}
227228
}
228229

@@ -276,25 +277,25 @@ impl PyCSimple {
276277
let value = unsafe { (*self.value.as_ptr()).clone() };
277278
if let Ok(i) = value.try_int(vm) {
278279
let i = i.as_bigint();
279-
if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u8().as_raw_ptr()) {
280-
return i.to_u8().map(|r: u8| libffi::middle::Arg::new(&r));
280+
return if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u8().as_raw_ptr()) {
281+
i.to_u8().map(|r: u8| libffi::middle::Arg::new(&r))
281282
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i8().as_raw_ptr()) {
282-
return i.to_i8().map(|r: i8| libffi::middle::Arg::new(&r));
283+
i.to_i8().map(|r: i8| libffi::middle::Arg::new(&r))
283284
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u16().as_raw_ptr()) {
284-
return i.to_u16().map(|r: u16| libffi::middle::Arg::new(&r));
285+
i.to_u16().map(|r: u16| libffi::middle::Arg::new(&r))
285286
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i16().as_raw_ptr()) {
286-
return i.to_i16().map(|r: i16| libffi::middle::Arg::new(&r));
287+
i.to_i16().map(|r: i16| libffi::middle::Arg::new(&r))
287288
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u32().as_raw_ptr()) {
288-
return i.to_u32().map(|r: u32| libffi::middle::Arg::new(&r));
289+
i.to_u32().map(|r: u32| libffi::middle::Arg::new(&r))
289290
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i32().as_raw_ptr()) {
290-
return i.to_i32().map(|r: i32| libffi::middle::Arg::new(&r));
291+
i.to_i32().map(|r: i32| libffi::middle::Arg::new(&r))
291292
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u64().as_raw_ptr()) {
292-
return i.to_u64().map(|r: u64| libffi::middle::Arg::new(&r));
293+
i.to_u64().map(|r: u64| libffi::middle::Arg::new(&r))
293294
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i64().as_raw_ptr()) {
294-
return i.to_i64().map(|r: i64| libffi::middle::Arg::new(&r));
295+
i.to_i64().map(|r: i64| libffi::middle::Arg::new(&r))
295296
} else {
296-
return None;
297-
}
297+
None
298+
};
298299
}
299300
if let Ok(_f) = value.try_float(vm) {
300301
todo!();
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
use crate::builtins::PyType;
2+
use crate::builtins::PyTypeRef;
3+
use crate::stdlib::ctypes::PyCData;
4+
use crate::types::Constructor;
5+
use crate::types::Representable;
6+
use crate::{Py, PyResult, VirtualMachine};
7+
8+
#[pyclass(name = "PyCFieldType", base = PyType, module = "_ctypes")]
9+
#[derive(PyPayload, Debug)]
10+
pub struct PyCFieldType {
11+
#[allow(dead_code)]
12+
pub(super) inner: PyCField,
13+
}
14+
15+
#[pyclass]
16+
impl PyCFieldType {}
17+
18+
#[pyclass(
19+
name = "CField",
20+
base = PyCData,
21+
metaclass = "PyCFieldType",
22+
module = "_ctypes"
23+
)]
24+
#[derive(Debug, PyPayload)]
25+
pub struct PyCField {
26+
byte_offset: usize,
27+
byte_size: usize,
28+
#[allow(unused)]
29+
index: usize,
30+
proto: PyTypeRef,
31+
anonymous: bool,
32+
bitfield_size: bool,
33+
bit_offset: u8,
34+
name: String,
35+
}
36+
37+
impl Representable for PyCField {
38+
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
39+
let tp_name = zelf.proto.name().to_string();
40+
if zelf.bitfield_size {
41+
Ok(format!(
42+
"<{} type={}, ofs={byte_offset}, bit_size={bitfield_size}, bit_offset={bit_offset}",
43+
zelf.name,
44+
tp_name,
45+
byte_offset = zelf.byte_offset,
46+
bitfield_size = zelf.bitfield_size,
47+
bit_offset = zelf.bit_offset
48+
))
49+
} else {
50+
Ok(format!(
51+
"<{} type={tp_name}, ofs={}, size={}",
52+
zelf.name, zelf.byte_offset, zelf.byte_size
53+
))
54+
}
55+
}
56+
}
57+
58+
#[derive(Debug, FromArgs)]
59+
pub struct PyCFieldConstructorArgs {
60+
// PyObject *name, PyObject *proto,
61+
// Py_ssize_t byte_size, Py_ssize_t byte_offset,
62+
// Py_ssize_t index, int _internal_use,
63+
// PyObject *bit_size_obj, PyObject *bit_offset_obj
64+
}
65+
66+
impl Constructor for PyCField {
67+
type Args = PyCFieldConstructorArgs;
68+
69+
fn py_new(_cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
70+
Err(vm.new_type_error("Cannot instantiate a PyCField".to_string()))
71+
}
72+
}
73+
74+
#[pyclass(flags(BASETYPE, IMMUTABLETYPE), with(Constructor, Representable))]
75+
impl PyCField {
76+
#[pygetset]
77+
fn size(&self) -> usize {
78+
self.byte_size
79+
}
80+
81+
#[pygetset]
82+
fn bit_size(&self) -> bool {
83+
self.bitfield_size
84+
}
85+
86+
#[pygetset]
87+
fn is_bitfield(&self) -> bool {
88+
self.bitfield_size
89+
}
90+
91+
#[pygetset]
92+
fn is_anonymous(&self) -> bool {
93+
self.anonymous
94+
}
95+
96+
#[pygetset]
97+
fn name(&self) -> String {
98+
self.name.clone()
99+
}
100+
101+
#[pygetset(name = "type")]
102+
fn type_(&self) -> PyTypeRef {
103+
self.proto.clone()
104+
}
105+
106+
#[pygetset]
107+
fn offset(&self) -> usize {
108+
self.byte_offset
109+
}
110+
111+
#[pygetset]
112+
fn byte_offset(&self) -> usize {
113+
self.byte_offset
114+
}
115+
116+
#[pygetset]
117+
fn byte_size(&self) -> usize {
118+
self.byte_size
119+
}
120+
121+
#[pygetset]
122+
fn bit_offset(&self) -> u8 {
123+
self.bit_offset
124+
}
125+
}

0 commit comments

Comments
 (0)