@@ -45,7 +45,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
4545
4646#[ pymodule]
4747pub ( crate ) mod _ctypes {
48- use super :: base:: PyCSimple ;
48+ use super :: base:: { CDataObject , PyCSimple } ;
4949 use crate :: builtins:: PyTypeRef ;
5050 use crate :: class:: StaticType ;
5151 use crate :: convert:: ToPyObject ;
@@ -159,14 +159,15 @@ pub(crate) mod _ctypes {
159159 }
160160
161161 /// Get the size of a ctypes type from its type object
162+ #[ allow( dead_code) ]
162163 pub fn get_size_from_type ( cls : & PyTypeRef , vm : & VirtualMachine ) -> PyResult < usize > {
163164 // Try to get _type_ attribute for simple types
164- if let Ok ( type_attr) = cls. as_object ( ) . get_attr ( "_type_" , vm) {
165- if let Ok ( s) = type_attr. str ( vm) {
166- let s = s . to_string ( ) ;
167- if s . len ( ) == 1 && SIMPLE_TYPE_CHARS . contains ( s . as_str ( ) ) {
168- return Ok ( get_size ( & s ) ) ;
169- }
165+ if let Ok ( type_attr) = cls. as_object ( ) . get_attr ( "_type_" , vm)
166+ && let Ok ( s) = type_attr. str ( vm)
167+ {
168+ let s = s . to_string ( ) ;
169+ if s . len ( ) == 1 && SIMPLE_TYPE_CHARS . contains ( s . as_str ( ) ) {
170+ return Ok ( get_size ( & s ) ) ;
170171 }
171172 }
172173 // Fall back to sizeof
@@ -180,138 +181,138 @@ pub(crate) mod _ctypes {
180181 vm : & VirtualMachine ,
181182 ) -> PyResult < PyObjectRef > {
182183 // Try to get _type_ attribute
183- if let Ok ( type_attr) = cls. as_object ( ) . get_attr ( "_type_" , vm) {
184- if let Ok ( s) = type_attr. str ( vm) {
185- let ty = s. to_string ( ) ;
186- return match ty. as_str ( ) {
187- "c" => {
188- // c_char - single byte
189- Ok ( vm. ctx . new_bytes ( bytes. to_vec ( ) ) . into ( ) )
190- }
191- "b" => {
192- // c_byte - signed char
193- let val = if !bytes. is_empty ( ) { bytes[ 0 ] as i8 } else { 0 } ;
194- Ok ( vm. ctx . new_int ( val) . into ( ) )
195- }
196- "B" => {
197- // c_ubyte - unsigned char
198- let val = if !bytes. is_empty ( ) { bytes[ 0 ] } else { 0 } ;
199- Ok ( vm. ctx . new_int ( val) . into ( ) )
200- }
201- "h" => {
202- // c_short
203- let val = if bytes. len ( ) >= 2 {
204- i16:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] ] )
205- } else {
206- 0
207- } ;
208- Ok ( vm. ctx . new_int ( val) . into ( ) )
209- }
210- "H" => {
211- // c_ushort
212- let val = if bytes. len ( ) >= 2 {
213- u16:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] ] )
214- } else {
215- 0
216- } ;
217- Ok ( vm. ctx . new_int ( val) . into ( ) )
218- }
219- "i" | "l" => {
220- // c_int, c_long (assuming 32-bit)
221- let val = if bytes. len ( ) >= 4 {
222- i32:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] )
184+ if let Ok ( type_attr) = cls. as_object ( ) . get_attr ( "_type_" , vm)
185+ && let Ok ( s) = type_attr. str ( vm)
186+ {
187+ let ty = s. to_string ( ) ;
188+ return match ty. as_str ( ) {
189+ "c" => {
190+ // c_char - single byte
191+ Ok ( vm. ctx . new_bytes ( bytes. to_vec ( ) ) . into ( ) )
192+ }
193+ "b" => {
194+ // c_byte - signed char
195+ let val = if !bytes. is_empty ( ) { bytes[ 0 ] as i8 } else { 0 } ;
196+ Ok ( vm. ctx . new_int ( val) . into ( ) )
197+ }
198+ "B" => {
199+ // c_ubyte - unsigned char
200+ let val = if !bytes. is_empty ( ) { bytes[ 0 ] } else { 0 } ;
201+ Ok ( vm. ctx . new_int ( val) . into ( ) )
202+ }
203+ "h" => {
204+ // c_short
205+ let val = if bytes. len ( ) >= 2 {
206+ i16:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] ] )
207+ } else {
208+ 0
209+ } ;
210+ Ok ( vm. ctx . new_int ( val) . into ( ) )
211+ }
212+ "H" => {
213+ // c_ushort
214+ let val = if bytes. len ( ) >= 2 {
215+ u16:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] ] )
216+ } else {
217+ 0
218+ } ;
219+ Ok ( vm. ctx . new_int ( val) . into ( ) )
220+ }
221+ "i" | "l" => {
222+ // c_int, c_long (assuming 32-bit)
223+ let val = if bytes. len ( ) >= 4 {
224+ i32:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] )
225+ } else {
226+ 0
227+ } ;
228+ Ok ( vm. ctx . new_int ( val) . into ( ) )
229+ }
230+ "I" | "L" => {
231+ // c_uint, c_ulong (assuming 32-bit)
232+ let val = if bytes. len ( ) >= 4 {
233+ u32:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] )
234+ } else {
235+ 0
236+ } ;
237+ Ok ( vm. ctx . new_int ( val) . into ( ) )
238+ }
239+ "q" => {
240+ // c_longlong
241+ let val = if bytes. len ( ) >= 8 {
242+ i64:: from_ne_bytes ( [
243+ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] , bytes[ 4 ] , bytes[ 5 ] , bytes[ 6 ] ,
244+ bytes[ 7 ] ,
245+ ] )
246+ } else {
247+ 0
248+ } ;
249+ Ok ( vm. ctx . new_int ( val) . into ( ) )
250+ }
251+ "Q" => {
252+ // c_ulonglong
253+ let val = if bytes. len ( ) >= 8 {
254+ u64:: from_ne_bytes ( [
255+ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] , bytes[ 4 ] , bytes[ 5 ] , bytes[ 6 ] ,
256+ bytes[ 7 ] ,
257+ ] )
258+ } else {
259+ 0
260+ } ;
261+ Ok ( vm. ctx . new_int ( val) . into ( ) )
262+ }
263+ "f" => {
264+ // c_float
265+ let val = if bytes. len ( ) >= 4 {
266+ f32:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] )
267+ } else {
268+ 0.0
269+ } ;
270+ Ok ( vm. ctx . new_float ( val as f64 ) . into ( ) )
271+ }
272+ "d" | "g" => {
273+ // c_double
274+ let val = if bytes. len ( ) >= 8 {
275+ f64:: from_ne_bytes ( [
276+ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] , bytes[ 4 ] , bytes[ 5 ] , bytes[ 6 ] ,
277+ bytes[ 7 ] ,
278+ ] )
279+ } else {
280+ 0.0
281+ } ;
282+ Ok ( vm. ctx . new_float ( val) . into ( ) )
283+ }
284+ "?" => {
285+ // c_bool
286+ let val = !bytes. is_empty ( ) && bytes[ 0 ] != 0 ;
287+ Ok ( vm. ctx . new_bool ( val) . into ( ) )
288+ }
289+ "P" | "z" | "Z" => {
290+ // Pointer types - return as integer address
291+ let val = if bytes. len ( ) >= mem:: size_of :: < usize > ( ) {
292+ let mut arr = [ 0u8 ; 8 ] ;
293+ arr[ ..bytes. len ( ) . min ( 8 ) ] . copy_from_slice ( & bytes[ ..bytes. len ( ) . min ( 8 ) ] ) ;
294+ usize:: from_ne_bytes ( arr)
295+ } else {
296+ 0
297+ } ;
298+ Ok ( vm. ctx . new_int ( val) . into ( ) )
299+ }
300+ "u" => {
301+ // c_wchar - wide character
302+ let val = if bytes. len ( ) >= mem:: size_of :: < WideChar > ( ) {
303+ let wc = if mem:: size_of :: < WideChar > ( ) == 2 {
304+ u16:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] ] ) as u32
223305 } else {
224- 0
225- } ;
226- Ok ( vm. ctx . new_int ( val) . into ( ) )
227- }
228- "I" | "L" => {
229- // c_uint, c_ulong (assuming 32-bit)
230- let val = if bytes. len ( ) >= 4 {
231306 u32:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] )
232- } else {
233- 0
234- } ;
235- Ok ( vm. ctx . new_int ( val) . into ( ) )
236- }
237- "q" => {
238- // c_longlong
239- let val = if bytes. len ( ) >= 8 {
240- i64:: from_ne_bytes ( [
241- bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] , bytes[ 4 ] , bytes[ 5 ] ,
242- bytes[ 6 ] , bytes[ 7 ] ,
243- ] )
244- } else {
245- 0
246- } ;
247- Ok ( vm. ctx . new_int ( val) . into ( ) )
248- }
249- "Q" => {
250- // c_ulonglong
251- let val = if bytes. len ( ) >= 8 {
252- u64:: from_ne_bytes ( [
253- bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] , bytes[ 4 ] , bytes[ 5 ] ,
254- bytes[ 6 ] , bytes[ 7 ] ,
255- ] )
256- } else {
257- 0
258- } ;
259- Ok ( vm. ctx . new_int ( val) . into ( ) )
260- }
261- "f" => {
262- // c_float
263- let val = if bytes. len ( ) >= 4 {
264- f32:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] )
265- } else {
266- 0.0
267- } ;
268- Ok ( vm. ctx . new_float ( val as f64 ) . into ( ) )
269- }
270- "d" | "g" => {
271- // c_double
272- let val = if bytes. len ( ) >= 8 {
273- f64:: from_ne_bytes ( [
274- bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] , bytes[ 4 ] , bytes[ 5 ] ,
275- bytes[ 6 ] , bytes[ 7 ] ,
276- ] )
277- } else {
278- 0.0
279- } ;
280- Ok ( vm. ctx . new_float ( val) . into ( ) )
281- }
282- "?" => {
283- // c_bool
284- let val = !bytes. is_empty ( ) && bytes[ 0 ] != 0 ;
285- Ok ( vm. ctx . new_bool ( val) . into ( ) )
286- }
287- "P" | "z" | "Z" => {
288- // Pointer types - return as integer address
289- let val = if bytes. len ( ) >= mem:: size_of :: < usize > ( ) {
290- let mut arr = [ 0u8 ; 8 ] ;
291- arr[ ..bytes. len ( ) . min ( 8 ) ] . copy_from_slice ( & bytes[ ..bytes. len ( ) . min ( 8 ) ] ) ;
292- usize:: from_ne_bytes ( arr)
293- } else {
294- 0
295307 } ;
296- Ok ( vm. ctx . new_int ( val) . into ( ) )
297- }
298- "u" => {
299- // c_wchar - wide character
300- let val = if bytes. len ( ) >= mem:: size_of :: < WideChar > ( ) {
301- let wc = if mem:: size_of :: < WideChar > ( ) == 2 {
302- u16:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] ] ) as u32
303- } else {
304- u32:: from_ne_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] )
305- } ;
306- char:: from_u32 ( wc) . unwrap_or ( '\0' )
307- } else {
308- '\0'
309- } ;
310- Ok ( vm. ctx . new_str ( val. to_string ( ) ) . into ( ) )
311- }
312- _ => Ok ( vm. ctx . none ( ) ) ,
313- } ;
314- }
308+ char:: from_u32 ( wc) . unwrap_or ( '\0' )
309+ } else {
310+ '\0'
311+ } ;
312+ Ok ( vm. ctx . new_str ( val. to_string ( ) ) . into ( ) )
313+ }
314+ _ => Ok ( vm. ctx . none ( ) ) ,
315+ } ;
315316 }
316317 // Default: return bytes as-is
317318 Ok ( vm. ctx . new_bytes ( bytes. to_vec ( ) ) . into ( ) )
@@ -339,9 +340,11 @@ pub(crate) mod _ctypes {
339340 } else if !SIMPLE_TYPE_CHARS . contains ( tp_str. as_str ( ) ) {
340341 Err ( vm. new_attribute_error ( format ! ( "class must define a '_type_' attribute which must be\n a single character string containing one of {SIMPLE_TYPE_CHARS}, currently it is {tp_str}." ) ) )
341342 } else {
343+ let size = get_size ( & tp_str) ;
342344 Ok ( PyCSimple {
343345 _type_ : tp_str,
344346 value : AtomicCell :: new ( vm. ctx . none ( ) ) ,
347+ cdata : rustpython_common:: lock:: PyRwLock :: new ( CDataObject :: new ( size) ) ,
345348 } )
346349 }
347350 } else {
0 commit comments