11use crate :: atomic_func;
22use crate :: builtins:: { PyBytes , PyInt } ;
3- use crate :: convert :: ToPyObject ;
4- use crate :: function:: FuncArgs ;
3+ use crate :: class :: StaticType ;
4+ use crate :: function:: { FuncArgs , KwArgs } ;
55use crate :: protocol:: {
66 BufferDescriptor , BufferMethods , PyBuffer , PyNumberMethods , PySequenceMethods ,
77} ;
88use crate :: stdlib:: ctypes:: base:: CDataObject ;
99use crate :: stdlib:: ctypes:: util:: StgInfo ;
1010use crate :: types:: { AsBuffer , AsNumber , AsSequence , Callable } ;
11- use crate :: { AsObject , Py , PyObjectRef , PyPayload } ;
11+ use crate :: { AsObject , Py , PyObjectRef , PyPayload , PyRef } ;
1212use crate :: {
1313 PyResult , VirtualMachine ,
1414 builtins:: { PyType , PyTypeRef } ,
@@ -22,6 +22,7 @@ use rustpython_vm::stdlib::ctypes::base::PyCData;
2222
2323#[ pyclass( name = "PyCArrayType" , base = PyType , module = "_ctypes" ) ]
2424pub struct PyCArrayType {
25+ pub base : PyType ,
2526 pub ( super ) stg_info : StgInfo ,
2627 pub ( super ) typ : PyRwLock < PyObjectRef > ,
2728 pub ( super ) length : AtomicCell < usize > ,
@@ -71,11 +72,94 @@ impl Callable for PyCArrayType {
7172 }
7273}
7374
75+ impl PyCArrayType {
76+ /// Create a new array type dynamically (like c_int * 5)
77+ pub fn create_array_type (
78+ element_type : PyObjectRef ,
79+ length : usize ,
80+ element_size : usize ,
81+ metatype : & Py < PyType > ,
82+ vm : & VirtualMachine ,
83+ ) -> PyResult < PyObjectRef > {
84+ use crate :: builtins:: PyTuple ;
85+ use crate :: function:: { FuncArgs , KwArgs } ;
86+
87+ let total_size = element_size * length;
88+ let stg_info = StgInfo :: new ( total_size, element_size) ;
89+
90+ // Create base PyType using type(name, bases, dict) pattern
91+ let name = vm
92+ . ctx
93+ . new_str ( format ! ( "{}_Array_{}" , metatype. name( ) , length) ) ;
94+ let bases = PyTuple :: new_ref ( vec ! [ element_type. clone( ) ] , & vm. ctx ) ;
95+ let dict = vm. ctx . new_dict ( ) ;
96+ dict. set_item ( "_length_" , vm. ctx . new_int ( length) . into ( ) , vm) ?;
97+ dict. set_item ( "_type_" , element_type. clone ( ) , vm) ?;
98+
99+ let args = FuncArgs :: new (
100+ vec ! [ name. into( ) , bases. into( ) , dict. into( ) ] ,
101+ KwArgs :: default ( ) ,
102+ ) ;
103+ let base = crate :: builtins:: type_:: PyType :: py_new ( metatype, args, vm) ?;
104+
105+ let payload = PyCArrayType {
106+ base,
107+ stg_info,
108+ typ : PyRwLock :: new ( element_type) ,
109+ length : AtomicCell :: new ( length) ,
110+ element_size : AtomicCell :: new ( element_size) ,
111+ } ;
112+ let array_metatype = PyCArrayType :: static_type ( ) ;
113+ let typ_ref = payload. into_ref_with_type ( vm, array_metatype. to_owned ( ) ) ?;
114+
115+ // Finalize heap type (register subclass, member descriptors, etc.)
116+ let type_ref: PyTypeRef = typ_ref
117+ . as_object ( )
118+ . to_owned ( )
119+ . downcast ( )
120+ . expect ( "metaclass should downcast to PyType" ) ;
121+ PyType :: finalize_heap_type ( & type_ref, KwArgs :: default ( ) , vm) ?;
122+
123+ Ok ( typ_ref. into ( ) )
124+ }
125+ }
126+
74127impl Constructor for PyCArrayType {
75- type Args = PyObjectRef ;
128+ type Args = FuncArgs ;
129+
130+ fn py_new ( metatype : & Py < PyType > , args : FuncArgs , vm : & VirtualMachine ) -> PyResult < Self > {
131+ // 1. Create the base type using PyType::py_new
132+ let base = crate :: builtins:: type_:: PyType :: py_new ( metatype, args, vm) ?;
133+
134+ // 2. Return PyCArrayType with the base and default values
135+ // The actual _length_ and _type_ will be set after type creation via __init__
136+ Ok ( PyCArrayType {
137+ base,
138+ stg_info : StgInfo :: default ( ) ,
139+ typ : PyRwLock :: new ( vm. ctx . none ( ) ) ,
140+ length : AtomicCell :: new ( 0 ) ,
141+ element_size : AtomicCell :: new ( 0 ) ,
142+ } )
143+ }
144+
145+ fn py_new_ref (
146+ metatype : PyTypeRef ,
147+ args : FuncArgs ,
148+ vm : & VirtualMachine ,
149+ ) -> PyResult < PyRef < Self > > {
150+ let payload = Self :: py_new ( & metatype, args, vm) ?;
151+ let array_metatype = PyCArrayType :: static_type ( ) ;
152+ let typ_ref = payload. into_ref_with_type ( vm, array_metatype. to_owned ( ) ) ?;
153+
154+ // Finalize heap type (register subclass, member descriptors, etc.)
155+ let type_ref: PyTypeRef = typ_ref
156+ . as_object ( )
157+ . to_owned ( )
158+ . downcast ( )
159+ . expect ( "metaclass should downcast to PyType" ) ;
160+ PyType :: finalize_heap_type ( & type_ref, KwArgs :: default ( ) , vm) ?;
76161
77- fn py_new ( _cls : & Py < PyType > , _args : Self :: Args , _vm : & VirtualMachine ) -> PyResult < Self > {
78- unreachable ! ( )
162+ Ok ( typ_ref)
79163 }
80164}
81165
@@ -107,16 +191,14 @@ impl PyCArrayType {
107191
108192 // Element size is the total size of the inner array
109193 let new_element_size = inner_length * inner_element_size;
110- let total_size = new_element_size * ( n as usize ) ;
111- let stg_info = StgInfo :: new ( total_size, inner_element_size) ;
112194
113- Ok ( PyCArrayType {
114- stg_info ,
115- typ : PyRwLock :: new ( current_array_type ) ,
116- length : AtomicCell :: new ( n as usize ) ,
117- element_size : AtomicCell :: new ( new_element_size ) ,
118- }
119- . to_pyobject ( vm ) )
195+ PyCArrayType :: create_array_type (
196+ current_array_type ,
197+ n as usize ,
198+ new_element_size ,
199+ zelf . class ( ) ,
200+ vm ,
201+ )
120202 }
121203
122204 #[ pyclassmethod]
0 commit comments