@@ -120,60 +120,106 @@ impl Debug for PyCFuncPtr {
120120}
121121
122122impl Constructor for PyCFuncPtr {
123- type Args = ( PyTupleRef , FuncArgs ) ;
123+ type Args = FuncArgs ;
124124
125- fn py_new ( _cls : PyTypeRef , ( tuple, _args) : Self :: Args , vm : & VirtualMachine ) -> PyResult {
126- let name = tuple
127- . first ( )
128- . ok_or ( vm. new_type_error ( "Expected a tuple with at least 2 elements" ) ) ?
129- . downcast_ref :: < PyStr > ( )
130- . ok_or ( vm. new_type_error ( "Expected a string" ) ) ?
131- . to_string ( ) ;
132- let handler = tuple
133- . into_iter ( )
134- . nth ( 1 )
135- . ok_or ( vm. new_type_error ( "Expected a tuple with at least 2 elements" ) ) ?
136- . clone ( ) ;
137- let handle = handler. try_int ( vm) ;
138- let handle = match handle {
139- Ok ( handle) => handle. as_bigint ( ) . clone ( ) ,
140- Err ( _) => handler
141- . get_attr ( "_handle" , vm) ?
142- . try_int ( vm) ?
143- . as_bigint ( )
144- . clone ( ) ,
145- } ;
146- let library_cache = crate :: stdlib:: ctypes:: library:: libcache ( ) . read ( ) ;
147- let library = library_cache
148- . get_lib (
149- handle
150- . to_usize ( )
151- . ok_or ( vm. new_value_error ( "Invalid handle" . to_string ( ) ) ) ?,
152- )
153- . ok_or_else ( || vm. new_value_error ( "Library not found" . to_string ( ) ) ) ?;
154- let inner_lib = library. lib . lock ( ) ;
155-
156- let terminated = format ! ( "{}\0 " , & name) ;
157- let code_ptr = if let Some ( lib) = & * inner_lib {
158- let pointer: Symbol < ' _ , FP > = unsafe {
159- lib. get ( terminated. as_bytes ( ) )
160- . map_err ( |err| err. to_string ( ) )
161- . map_err ( |err| vm. new_attribute_error ( err) ) ?
125+ fn py_new ( cls : PyTypeRef , args : Self :: Args , vm : & VirtualMachine ) -> PyResult {
126+ // Handle different argument forms like CPython:
127+ // 1. Empty args: create uninitialized
128+ // 2. One integer argument: function address
129+ // 3. Tuple argument: (name, dll) form
130+
131+ if args. args . is_empty ( ) {
132+ return Self {
133+ ptr : PyRwLock :: new ( None ) ,
134+ needs_free : AtomicCell :: new ( false ) ,
135+ arg_types : PyRwLock :: new ( None ) ,
136+ _flags_ : AtomicCell :: new ( 0 ) ,
137+ res_type : PyRwLock :: new ( None ) ,
138+ name : PyRwLock :: new ( None ) ,
139+ handler : vm. ctx . none ( ) ,
140+ }
141+ . into_ref_with_type ( vm, cls)
142+ . map ( Into :: into) ;
143+ }
144+
145+ let first_arg = & args. args [ 0 ] ;
146+
147+ // Check if first argument is an integer (function address)
148+ if let Ok ( addr) = first_arg. try_int ( vm) {
149+ let ptr_val = addr. as_bigint ( ) . to_usize ( ) . unwrap_or ( 0 ) ;
150+ return Self {
151+ ptr : PyRwLock :: new ( Some ( CodePtr ( ptr_val as * mut _ ) ) ) ,
152+ needs_free : AtomicCell :: new ( false ) ,
153+ arg_types : PyRwLock :: new ( None ) ,
154+ _flags_ : AtomicCell :: new ( 0 ) ,
155+ res_type : PyRwLock :: new ( None ) ,
156+ name : PyRwLock :: new ( Some ( format ! ( "CFuncPtr@{:#x}" , ptr_val) ) ) ,
157+ handler : vm. ctx . new_int ( ptr_val) . into ( ) ,
158+ }
159+ . into_ref_with_type ( vm, cls)
160+ . map ( Into :: into) ;
161+ }
162+
163+ // Check if first argument is a tuple (name, dll) form
164+ if let Some ( tuple) = first_arg. downcast_ref :: < PyTuple > ( ) {
165+ let name = tuple
166+ . first ( )
167+ . ok_or ( vm. new_type_error ( "Expected a tuple with at least 2 elements" ) ) ?
168+ . downcast_ref :: < PyStr > ( )
169+ . ok_or ( vm. new_type_error ( "Expected a string" ) ) ?
170+ . to_string ( ) ;
171+ let handler = tuple
172+ . iter ( )
173+ . nth ( 1 )
174+ . ok_or ( vm. new_type_error ( "Expected a tuple with at least 2 elements" ) ) ?
175+ . clone ( ) ;
176+
177+ // Get library handle and load function
178+ let handle = handler. try_int ( vm) ;
179+ let handle = match handle {
180+ Ok ( handle) => handle. as_bigint ( ) . clone ( ) ,
181+ Err ( _) => handler
182+ . get_attr ( "_handle" , vm) ?
183+ . try_int ( vm) ?
184+ . as_bigint ( )
185+ . clone ( ) ,
162186 } ;
163- Some ( CodePtr ( * pointer as * mut _ ) )
164- } else {
165- None
166- } ;
167- Ok ( Self {
168- ptr : PyRwLock :: new ( code_ptr) ,
169- needs_free : AtomicCell :: new ( false ) ,
170- arg_types : PyRwLock :: new ( None ) ,
171- _flags_ : AtomicCell :: new ( 0 ) ,
172- res_type : PyRwLock :: new ( None ) ,
173- name : PyRwLock :: new ( Some ( name) ) ,
174- handler,
187+ let library_cache = crate :: stdlib:: ctypes:: library:: libcache ( ) . read ( ) ;
188+ let library = library_cache
189+ . get_lib (
190+ handle
191+ . to_usize ( )
192+ . ok_or ( vm. new_value_error ( "Invalid handle" . to_string ( ) ) ) ?,
193+ )
194+ . ok_or_else ( || vm. new_value_error ( "Library not found" . to_string ( ) ) ) ?;
195+ let inner_lib = library. lib . lock ( ) ;
196+
197+ let terminated = format ! ( "{}\0 " , & name) ;
198+ let code_ptr = if let Some ( lib) = & * inner_lib {
199+ let pointer: Symbol < ' _ , FP > = unsafe {
200+ lib. get ( terminated. as_bytes ( ) )
201+ . map_err ( |err| err. to_string ( ) )
202+ . map_err ( |err| vm. new_attribute_error ( err) ) ?
203+ } ;
204+ Some ( CodePtr ( * pointer as * mut _ ) )
205+ } else {
206+ None
207+ } ;
208+
209+ return Self {
210+ ptr : PyRwLock :: new ( code_ptr) ,
211+ needs_free : AtomicCell :: new ( false ) ,
212+ arg_types : PyRwLock :: new ( None ) ,
213+ _flags_ : AtomicCell :: new ( 0 ) ,
214+ res_type : PyRwLock :: new ( None ) ,
215+ name : PyRwLock :: new ( Some ( name) ) ,
216+ handler,
217+ }
218+ . into_ref_with_type ( vm, cls)
219+ . map ( Into :: into) ;
175220 }
176- . to_pyobject ( vm) )
221+
222+ Err ( vm. new_type_error ( "Expected an integer address or a tuple" ) )
177223 }
178224}
179225
0 commit comments