Skip to content

Commit 1bfe8fb

Browse files
committed
add more classes
1 parent ac379ce commit 1bfe8fb

File tree

5 files changed

+123
-5
lines changed

5 files changed

+123
-5
lines changed

vm/src/stdlib/ctypes.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
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;
910
pub(crate) mod union;
11+
pub(crate) mod util;
1012

1113
use crate::builtins::PyModule;
1214
use crate::class::PyClassImpl;

vm/src/stdlib/ctypes/field.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use crate::builtins::PyType;
2+
3+
#[pyclass(name = "PyCFieldType", base = "PyType", module = "_ctypes")]
4+
#[derive(PyPayload)]
5+
pub struct PyCFieldType {
6+
pub(super) inner: PyCField,
7+
}
8+
9+
#[pyclass]
10+
impl PyCFieldType {}
11+
12+
#[pyclass(
13+
name = "CField",
14+
base = "PyCData",
15+
metaclass = "PyCFieldType",
16+
module = "_ctypes"
17+
)]
18+
pub struct PyCField {
19+
byte_offset: usize,
20+
byte_size: usize,
21+
index: usize,
22+
proto: PyTypeRef,
23+
anonymous: bool,
24+
bitfield_size: bool,
25+
bit_offset: u8,
26+
name: String,
27+
}
28+
29+
impl Representable for PyCFuncPtr {
30+
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
31+
let field = zelf.inner.read();
32+
let tp_name = field.proto.name().to_string();
33+
if field.bitfield_size != 0 {
34+
Ok(format!(
35+
"<{} {} type={}, ofs={}, bit_size={}, bit_offset={}",
36+
field.name, tp_name, field.byte_offset, field.bitfield_size, field.bit_offset
37+
))
38+
} else {
39+
Ok(format!(
40+
"<{} {} type={}, ofs={}, size={}",
41+
field.name, tp_name, field.byte_offset, field.byte_size
42+
))
43+
}
44+
}
45+
}
46+
47+
#[pyclass(flags(BASETYPE, IMMUTABLETYPE), with(Representable))]
48+
impl PyCField {
49+
#[pygetset]
50+
fn size(&self) -> usize {
51+
self.byte_size
52+
}
53+
54+
#[pygetset]
55+
fn bit_size(&self) -> u8 {
56+
self.bitfield_size
57+
}
58+
59+
#[pygetset]
60+
fn is_bitfield(&self) -> bool {
61+
self.bitfield_size
62+
}
63+
64+
#[pygetset]
65+
fn is_anonymous(&self) -> bool {
66+
self.anonymous
67+
}
68+
}

vm/src/stdlib/ctypes/function.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,37 @@ use libffi::middle::{Arg, Cif, CodePtr, Type};
1313
use libloading::Symbol;
1414
use num_traits::ToPrimitive;
1515
use rustpython_common::lock::PyRwLock;
16+
use std::ffi;
1617
use std::fmt::Debug;
1718

1819
// https://github.com/python/cpython/blob/4f8bb3947cfbc20f970ff9d9531e1132a9e95396/Modules/_ctypes/callproc.c#L15
1920

21+
/// Returns none if the `_type_` attribute cannot be found/converted to a string
22+
fn get_type_char(ty: PyTypeRef) -> Option<String> {
23+
// PyTypeRef could be c_int, c_float, c_double, etc., we need to get the _type_ attribute
24+
// and convert it to a Type
25+
let type_str = ty.get_attr("_type_")?;
26+
let type_str = type_str.downcast_ref::<PyStr>()?.to_string();
27+
Some(type_str)
28+
}
29+
30+
fn type_ref_to_type(ty: PyTypeRef) -> Type {
31+
// PyTypeRef could be c_int, c_float, c_double, etc., we need to get the _type_ attribute
32+
// and convert it to a Type
33+
unimplemented!()
34+
}
35+
36+
fn obj_from_type_ref_and_data(data: ffi::c_void, ty: PyTypeRef) -> PyObjectRef {
37+
unimplemented!()
38+
}
39+
2040
#[derive(Debug)]
2141
pub struct Function {
2242
args: Vec<Type>,
2343
// TODO: no protection from use-after-free
2444
pointer: CodePtr,
2545
cif: Cif,
46+
return_type: Option<PyTypeRef>,
2647
}
2748

2849
unsafe impl Send for Function {}
@@ -85,7 +106,7 @@ impl Function {
85106
.map_err(|err| vm.new_attribute_error(err))?
86107
};
87108
let code_ptr = CodePtr(*pointer as *mut _);
88-
let return_type = match ret_type {
109+
let return_type = match ret_type.clone() {
89110
// TODO: Fix this
90111
Some(_t) => {
91112
return Err(vm.new_not_implemented_error("Return type not implemented".to_string()));
@@ -97,6 +118,7 @@ impl Function {
97118
args,
98119
cif,
99120
pointer: code_ptr,
121+
return_type: ret_type,
100122
})
101123
}
102124

@@ -119,8 +141,7 @@ impl Function {
119141
Err(vm.new_type_error("Expected a ctypes simple type".to_string()))
120142
})
121143
.collect::<PyResult<Vec<Arg>>>()?;
122-
// TODO: FIX return
123-
let result: i32 = unsafe { self.cif.call(self.pointer, &args) };
144+
let result: ffi::c_void = unsafe { self.cif.call(self.pointer, &args) };
124145
Ok(vm.ctx.new_int(result).into())
125146
}
126147
}

vm/src/stdlib/ctypes/pointer.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
crate::builtins::PyType;
1+
use crate::builtins::PyType;
22

33
#[pyclass(name = "PyCPointerType", base = "PyType", module = "_ctypes")]
44
#[derive(PyPayload)]
@@ -9,7 +9,12 @@ pub struct PyCPointerType {
99
#[pyclass]
1010
impl PyCPointerType {}
1111

12-
#[pyclass(name = "_Pointer", base = "PyCData", metaclass = "PyCPointerType", module = "_ctypes")]
12+
#[pyclass(
13+
name = "_Pointer",
14+
base = "PyCData",
15+
metaclass = "PyCPointerType",
16+
module = "_ctypes"
17+
)]
1318
pub struct PyCPointer {}
1419

1520
#[pyclass(flags(BASETYPE, IMMUTABLETYPE))]

vm/src/stdlib/ctypes/util.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#[pyclass]
2+
#[derive(Debug, PyPayload)]
3+
pub struct StgInfo {
4+
initialized: i32,
5+
size: usize, // number of bytes
6+
align: usize, // alignment requirements
7+
length: usize, // number of fields
8+
ffi_type_pointer: ffi::ffi_type,
9+
proto: PyObjectRef, // Only for Pointer/ArrayObject
10+
setfunc: Option<PyObjectRef>, // Only for simple objects
11+
getfunc: Option<PyObjectRef>, // Only for simple objects
12+
paramfunc: Option<PyObjectRef>,
13+
14+
/* Following fields only used by PyCFuncPtrType_Type instances */
15+
argtypes: Option<PyObjectRef>, // tuple of CDataObjects
16+
converters: Option<PyObjectRef>, // tuple([t.from_param for t in argtypes])
17+
restype: Option<PyObjectRef>, // CDataObject or NULL
18+
checker: Option<PyObjectRef>,
19+
module: Option<PyObjectRef>,
20+
flags: i32, // calling convention and such
21+
dict_final: u8,
22+
}

0 commit comments

Comments
 (0)