Skip to content

Commit 4fcce4d

Browse files
authored
ctypes struct/union/array (RustPython#6309)
* PyCStructure * impl union * array * temp remove * apply review
1 parent 95b8c60 commit 4fcce4d

File tree

7 files changed

+1003
-99
lines changed

7 files changed

+1003
-99
lines changed

crates/vm/src/stdlib/ctypes.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ pub fn extend_module_nodes(vm: &VirtualMachine, module: &Py<PyModule>) {
2121
array::PyCArrayType::make_class(ctx);
2222
field::PyCFieldType::make_class(ctx);
2323
pointer::PyCPointerType::make_class(ctx);
24+
structure::PyCStructType::make_class(ctx);
25+
union::PyCUnionType::make_class(ctx);
2426
extend_module!(vm, module, {
2527
"_CData" => PyCData::make_class(ctx),
2628
"_SimpleCData" => PyCSimple::make_class(ctx),
@@ -46,9 +48,10 @@ pub(crate) mod _ctypes {
4648
use super::base::PyCSimple;
4749
use crate::builtins::PyTypeRef;
4850
use crate::class::StaticType;
51+
use crate::convert::ToPyObject;
4952
use crate::function::{Either, FuncArgs, OptionalArg};
5053
use crate::stdlib::ctypes::library;
51-
use crate::{AsObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine};
54+
use crate::{AsObject, PyObjectRef, PyPayload, PyResult, TryFromObject, VirtualMachine};
5255
use crossbeam_utils::atomic::AtomicCell;
5356
use std::ffi::{
5457
c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong,
@@ -57,6 +60,23 @@ pub(crate) mod _ctypes {
5760
use std::mem;
5861
use widestring::WideChar;
5962

63+
/// CArgObject - returned by byref()
64+
#[pyclass(name = "CArgObject", module = "_ctypes", no_attr)]
65+
#[derive(Debug, PyPayload)]
66+
pub struct CArgObject {
67+
pub obj: PyObjectRef,
68+
#[allow(dead_code)]
69+
pub offset: isize,
70+
}
71+
72+
#[pyclass]
73+
impl CArgObject {
74+
#[pygetset]
75+
fn _obj(&self) -> PyObjectRef {
76+
self.obj.clone()
77+
}
78+
}
79+
6080
#[pyattr(name = "__version__")]
6181
const __VERSION__: &str = "1.1.0";
6282

@@ -322,9 +342,28 @@ pub(crate) mod _ctypes {
322342
}
323343

324344
#[pyfunction]
325-
fn byref(_args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
326-
// TODO: RUSTPYTHON
327-
Err(vm.new_value_error("not implemented"))
345+
fn byref(obj: PyObjectRef, offset: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult {
346+
use super::base::PyCData;
347+
use crate::class::StaticType;
348+
349+
// Check if obj is a ctypes instance
350+
if !obj.fast_isinstance(PyCData::static_type())
351+
&& !obj.fast_isinstance(PyCSimple::static_type())
352+
{
353+
return Err(vm.new_type_error(format!(
354+
"byref() argument must be a ctypes instance, not '{}'",
355+
obj.class().name()
356+
)));
357+
}
358+
359+
let offset_val = offset.unwrap_or(0);
360+
361+
// Create CArgObject to hold the reference
362+
Ok(CArgObject {
363+
obj,
364+
offset: offset_val,
365+
}
366+
.to_pyobject(vm))
328367
}
329368

330369
#[pyfunction]
@@ -380,9 +419,24 @@ pub(crate) mod _ctypes {
380419
f as usize
381420
}
382421

422+
#[pyattr]
423+
fn _wstring_at_addr(_vm: &VirtualMachine) -> usize {
424+
// Return address of wcsnlen or similar wide string function
425+
#[cfg(not(target_os = "windows"))]
426+
{
427+
let f = libc::wcslen;
428+
f as usize
429+
}
430+
#[cfg(target_os = "windows")]
431+
{
432+
// FIXME: On Windows, use wcslen from ucrt
433+
0
434+
}
435+
}
436+
383437
#[pyattr]
384438
fn _cast_addr(_vm: &VirtualMachine) -> usize {
385-
// TODO: RUSTPYTHON
439+
// todo!("Implement _cast_addr")
386440
0
387441
}
388442
}

0 commit comments

Comments
 (0)