|
1 | | -use crate::abstract_::{dict_to_kwargs, tuple_to_args}; |
2 | 1 | use crate::descrobject::{PyGetSetDef, PyMemberDef}; |
3 | 2 | use crate::methodobject::{PyMethodDef, build_method_def}; |
4 | 3 | use crate::object::define_py_check; |
5 | 4 | use crate::pystate::with_vm; |
6 | 5 | use crate::slots::{PySlot, PySlotKind, PySlotType}; |
7 | 6 | use crate::util::CStrExt; |
8 | 7 | use core::ffi::{c_char, c_int, c_ulong, c_void}; |
9 | | -use rustpython_vm::builtins::{PyDict, PyStr, PyTuple, PyType}; |
10 | | -use rustpython_vm::function::{FuncArgs, PyMethodFlags}; |
11 | | -use rustpython_vm::types::{PyTypeFlags, PyTypeSlots, SlotAccessor}; |
| 8 | +use core::mem::transmute; |
| 9 | +use rustpython_vm::builtins::{PyStr, PyType}; |
| 10 | +use rustpython_vm::function::PyMethodFlags; |
| 11 | +use rustpython_vm::types::{CSlotId, CSlots, PyTypeFlags, PyTypeSlots, SlotAccessor}; |
12 | 12 | use rustpython_vm::{AsObject, Py, PyObject}; |
| 13 | +use std::ptr; |
13 | 14 |
|
14 | 15 | pub type PyTypeObject = Py<PyType>; |
15 | 16 |
|
@@ -99,63 +100,26 @@ pub unsafe extern "C" fn PyType_GetFullyQualifiedName(ptr: *const PyTypeObject) |
99 | 100 |
|
100 | 101 | #[unsafe(no_mangle)] |
101 | 102 | pub unsafe extern "C" fn PyType_GetSlot(ty: *const PyTypeObject, slot: c_int) -> *mut c_void { |
102 | | - with_vm(|_vm| { |
103 | | - let ty = unsafe { &*ty }; |
104 | | - let slot: u8 = slot |
105 | | - .try_into() |
106 | | - .expect("slot number out of range for SlotAccessor"); |
107 | | - let slot_accessor: SlotAccessor = slot |
108 | | - .try_into() |
109 | | - .expect("invalid slot number for SlotAccessor"); |
110 | | - |
111 | | - match slot_accessor { |
112 | | - SlotAccessor::TpNew => { |
113 | | - extern "C" fn newfunc_wrapper( |
114 | | - subtype: *mut PyTypeObject, |
115 | | - args: *mut PyObject, |
116 | | - kwargs: *mut PyObject, |
117 | | - ) -> *mut PyObject { |
118 | | - with_vm(|vm| { |
119 | | - let subtype = unsafe { &*subtype }; |
120 | | - |
121 | | - let args = if let Some(args_obj) = unsafe { args.as_ref() } { |
122 | | - tuple_to_args(args_obj.try_downcast_ref::<PyTuple>(vm)?) |
123 | | - } else { |
124 | | - ().into() |
125 | | - }; |
126 | | - |
127 | | - let kwargs = unsafe { kwargs.as_ref() } |
128 | | - .map(|obj| dict_to_kwargs(vm, obj.try_downcast_ref::<PyDict>(vm)?)) |
129 | | - .transpose()? |
130 | | - .unwrap_or_default(); |
131 | | - |
132 | | - subtype |
133 | | - .slots |
134 | | - .new |
135 | | - .load() |
136 | | - .expect("tp_new slot function pointer is null")( |
137 | | - subtype.to_owned(), |
138 | | - FuncArgs::new(args, kwargs), |
139 | | - vm, |
140 | | - ) |
141 | | - }) |
142 | | - } |
143 | | - |
144 | | - ty.slots.new.load().map(|_| newfunc_wrapper as *mut c_void) |
145 | | - } |
146 | | - _ => { |
147 | | - todo!("Slot {slot_accessor:?} for {ty:?} is not yet implemented in PyType_GetSlot") |
148 | | - } |
149 | | - } |
150 | | - .unwrap_or_default() |
151 | | - }) |
| 103 | + let ty = unsafe { &*ty }; |
| 104 | + eprintln!("PyType_GetSlot({:?}, {:?})", ty, slot); |
| 105 | + let Some(c_slots) = ty.slots.c_slots() else { |
| 106 | + return ptr::null_mut(); |
| 107 | + }; |
| 108 | + match CSlotId::from_raw(slot) { |
| 109 | + Some(CSlotId::TpNew) => c_slots |
| 110 | + .new |
| 111 | + .load() |
| 112 | + .map_or(ptr::null_mut(), |f| f as *mut c_void), |
| 113 | + None => ptr::null_mut(), |
| 114 | + } |
152 | 115 | } |
153 | 116 |
|
154 | 117 | #[unsafe(no_mangle)] |
155 | 118 | pub extern "C" fn PyType_FromSlots(slots: *const PySlot) -> *mut PyObject { |
156 | 119 | with_vm(|vm| { |
157 | 120 | let mut name = None; |
158 | 121 | let mut base = None; |
| 122 | + let c_slots = CSlots::new(); |
159 | 123 | let mut methods = Vec::new(); |
160 | 124 | let mut type_slots: PyTypeSlots = Default::default(); |
161 | 125 | let attrs = Default::default(); |
@@ -192,9 +156,12 @@ pub extern "C" fn PyType_FromSlots(slots: *const PySlot) -> *mut PyObject { |
192 | 156 | type_slots.doc = doc; |
193 | 157 | } |
194 | 158 | SlotAccessor::TpNew => { |
195 | | - type_slots.new.store(Some(|ty, _args, vm| { |
196 | | - Err(vm.new_not_implemented_error(format!("tp_new is not yet implemented in PyType_FromSlots for {ty:?}"))) |
197 | | - })); |
| 159 | + let tp_new = unsafe { transmute(slot.pfunc) }; |
| 160 | + c_slots.new.store(Some(tp_new)); |
| 161 | + let def = vm |
| 162 | + .ctx |
| 163 | + .new_method_def("__new__", PyType::__new__, PyMethodFlags::METHOD, None); |
| 164 | + methods.push(("__new__", def.into())); |
198 | 165 | } |
199 | 166 | SlotAccessor::TpBase => { |
200 | 167 | base = unsafe { Some(&*slot.pfunc.cast::<PyTypeObject>()) } |
@@ -257,6 +224,7 @@ pub extern "C" fn PyType_FromSlots(slots: *const PySlot) -> *mut PyObject { |
257 | 224 | vm.new_system_error(format!("Failed to create type from slots: {msg}")) |
258 | 225 | })?; |
259 | 226 |
|
| 227 | + class.set_c_slots(c_slots, vm)?; |
260 | 228 | let mut attrs = class.attributes.write(); |
261 | 229 | let class_static = unsafe { &*((&*class) as *const _) }; |
262 | 230 | for (name, method) in methods { |
|
0 commit comments