Skip to content

Commit 9ac6746

Browse files
committed
Update Lib/ctypes/__init__.py from cpython3.13.9
1 parent 8d18b85 commit 9ac6746

File tree

2 files changed

+80
-35
lines changed

2 files changed

+80
-35
lines changed

Lib/ctypes/__init__.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,19 @@ def __init__(self, name, mode=DEFAULT_MODE, handle=None,
347347
use_errno=False,
348348
use_last_error=False,
349349
winmode=None):
350+
if name:
351+
name = _os.fspath(name)
352+
353+
# If the filename that has been provided is an iOS/tvOS/watchOS
354+
# .fwork file, dereference the location to the true origin of the
355+
# binary.
356+
if name.endswith(".fwork"):
357+
with open(name) as f:
358+
name = _os.path.join(
359+
_os.path.dirname(_sys.executable),
360+
f.read().strip()
361+
)
362+
350363
self._name = name
351364
flags = self._func_flags_
352365
if use_errno:
@@ -467,6 +480,8 @@ def LoadLibrary(self, name):
467480

468481
if _os.name == "nt":
469482
pythonapi = PyDLL("python dll", None, _sys.dllhandle)
483+
elif _sys.platform == "android":
484+
pythonapi = PyDLL("libpython%d.%d.so" % _sys.version_info[:2])
470485
elif _sys.platform == "cygwin":
471486
pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
472487
else:
@@ -498,15 +513,14 @@ def WinError(code=None, descr=None):
498513
c_ssize_t = c_longlong
499514

500515
# functions
516+
501517
from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
502518

503519
## void *memmove(void *, const void *, size_t);
504-
# XXX: RUSTPYTHON
505-
# memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
520+
memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
506521

507522
## void *memset(void *, int, size_t)
508-
# XXX: RUSTPYTHON
509-
# memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
523+
memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
510524

511525
def PYFUNCTYPE(restype, *argtypes):
512526
class CFunctionType(_CFuncPtr):
@@ -515,30 +529,27 @@ class CFunctionType(_CFuncPtr):
515529
_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
516530
return CFunctionType
517531

518-
# XXX: RUSTPYTHON
519-
# _cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
532+
_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
520533
def cast(obj, typ):
521534
return _cast(obj, obj, typ)
522535

523-
# XXX: RUSTPYTHON
524-
# _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
536+
_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
525537
def string_at(ptr, size=-1):
526-
"""string_at(addr[, size]) -> string
538+
"""string_at(ptr[, size]) -> string
527539
528-
Return the string at addr."""
540+
Return the byte string at void *ptr."""
529541
return _string_at(ptr, size)
530542

531543
try:
532544
from _ctypes import _wstring_at_addr
533545
except ImportError:
534546
pass
535547
else:
536-
# XXX: RUSTPYTHON
537-
# _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
548+
_wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
538549
def wstring_at(ptr, size=-1):
539-
"""wstring_at(addr[, size]) -> string
550+
"""wstring_at(ptr[, size]) -> string
540551
541-
Return the string at addr."""
552+
Return the wide-character string at void *ptr."""
542553
return _wstring_at(ptr, size)
543554

544555

crates/vm/src/stdlib/ctypes/function.rs

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// spell-checker:disable
22

3-
use crate::builtins::{PyStr, PyTupleRef, PyTypeRef};
3+
use crate::builtins::{PyStr, PyTypeRef};
44
use crate::convert::ToPyObject;
55
use crate::function::FuncArgs;
66
use crate::stdlib::ctypes::PyCData;
@@ -142,27 +142,61 @@ impl Debug for PyCFuncPtr {
142142
}
143143

144144
impl Constructor for PyCFuncPtr {
145-
type Args = (PyTupleRef, FuncArgs);
146-
147-
fn py_new(_cls: PyTypeRef, (tuple, _args): Self::Args, vm: &VirtualMachine) -> PyResult {
148-
let name = tuple
149-
.first()
150-
.ok_or(vm.new_type_error("Expected a tuple with at least 2 elements"))?
151-
.downcast_ref::<PyStr>()
152-
.ok_or(vm.new_type_error("Expected a string"))?
153-
.to_string();
154-
let handler = tuple
155-
.into_iter()
156-
.nth(1)
157-
.ok_or(vm.new_type_error("Expected a tuple with at least 2 elements"))?
158-
.clone();
159-
Ok(Self {
160-
_flags_: AtomicCell::new(0),
161-
name: PyRwLock::new(name),
162-
_restype_: PyRwLock::new(None),
163-
handler,
145+
type Args = FuncArgs;
146+
147+
fn py_new(_cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
148+
// Handle different argument forms like CPython:
149+
// 1. One integer argument: function address
150+
// 2. Tuple argument: (name, dll) form
151+
152+
if args.args.is_empty() {
153+
// Empty args - create uninitialized
154+
return Ok(Self {
155+
_flags_: AtomicCell::new(0),
156+
name: PyRwLock::new(String::new()),
157+
_restype_: PyRwLock::new(None),
158+
handler: vm.ctx.none(),
159+
}
160+
.to_pyobject(vm));
161+
}
162+
163+
let first_arg = &args.args[0];
164+
165+
// Check if first argument is an integer (function address)
166+
if let Ok(addr) = first_arg.try_int(vm) {
167+
let ptr = addr.as_bigint().to_usize().unwrap_or(0);
168+
return Ok(Self {
169+
_flags_: AtomicCell::new(0),
170+
name: PyRwLock::new(format!("CFuncPtr@{:#x}", ptr)),
171+
_restype_: PyRwLock::new(None),
172+
handler: vm.ctx.new_int(ptr).into(),
173+
}
174+
.to_pyobject(vm));
175+
}
176+
177+
// Check if first argument is a tuple (name, dll) form
178+
if let Some(tuple) = first_arg.downcast_ref::<crate::builtins::PyTuple>() {
179+
let name = tuple
180+
.first()
181+
.ok_or(vm.new_type_error("Expected a tuple with at least 2 elements"))?
182+
.downcast_ref::<PyStr>()
183+
.ok_or(vm.new_type_error("Expected a string"))?
184+
.to_string();
185+
let handler = tuple
186+
.iter()
187+
.nth(1)
188+
.ok_or(vm.new_type_error("Expected a tuple with at least 2 elements"))?
189+
.clone();
190+
return Ok(Self {
191+
_flags_: AtomicCell::new(0),
192+
name: PyRwLock::new(name),
193+
_restype_: PyRwLock::new(None),
194+
handler,
195+
}
196+
.to_pyobject(vm));
164197
}
165-
.to_pyobject(vm))
198+
199+
Err(vm.new_type_error("Expected an integer address or a tuple"))
166200
}
167201
}
168202

0 commit comments

Comments
 (0)