@@ -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