Skip to content

Commit 8d18b85

Browse files
committed
Fix ctypes import blockers
1 parent 0e6e256 commit 8d18b85

File tree

2 files changed

+83
-7
lines changed

2 files changed

+83
-7
lines changed

crates/vm/src/stdlib/ctypes.rs

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,16 +199,30 @@ pub(crate) mod _ctypes {
199199

200200
#[pyfunction(name = "dlopen")]
201201
fn load_library_unix(
202-
name: String,
202+
name: Option<String>,
203203
_load_flags: OptionalArg<i32>,
204204
vm: &VirtualMachine,
205205
) -> PyResult<usize> {
206206
// TODO: audit functions first
207207
// TODO: load_flags
208-
let cache = library::libcache();
209-
let mut cache_write = cache.write();
210-
let (id, _) = cache_write.get_or_insert_lib(&name, vm).unwrap();
211-
Ok(id)
208+
match name {
209+
Some(name) => {
210+
let cache = library::libcache();
211+
let mut cache_write = cache.write();
212+
let (id, _) = cache_write
213+
.get_or_insert_lib(&name, vm)
214+
.map_err(|e| vm.new_os_error(e.to_string()))?;
215+
Ok(id)
216+
}
217+
None => {
218+
// If None, call libc::dlopen(null, mode) to get the current process handle
219+
let handle = unsafe { libc::dlopen(std::ptr::null(), libc::RTLD_NOW) };
220+
if handle.is_null() {
221+
return Err(vm.new_os_error("dlopen() error".to_string()));
222+
}
223+
Ok(handle as usize)
224+
}
225+
}
212226
}
213227

214228
#[pyfunction(name = "FreeLibrary")]
@@ -220,10 +234,57 @@ pub(crate) mod _ctypes {
220234
}
221235

222236
#[pyfunction(name = "POINTER")]
223-
pub fn pointer(_cls: PyTypeRef) {}
237+
pub fn create_pointer_type(cls: PyObjectRef, vm: &VirtualMachine) -> PyResult {
238+
// Get the _pointer_type_cache
239+
let ctypes_module = vm.import("_ctypes", 0)?;
240+
let cache = ctypes_module.get_attr("_pointer_type_cache", vm)?;
241+
242+
// Check if already in cache using __getitem__
243+
if let Ok(cached) = vm.call_method(&cache, "__getitem__", (cls.clone(),)) {
244+
if !vm.is_none(&cached) {
245+
return Ok(cached);
246+
}
247+
}
248+
249+
// Get the _Pointer base class
250+
let pointer_base = ctypes_module.get_attr("_Pointer", vm)?;
251+
252+
// Create the name for the pointer type
253+
let name = if let Ok(type_obj) = cls.get_attr("__name__", vm) {
254+
format!("LP_{}", type_obj.str(vm)?)
255+
} else if let Ok(s) = cls.str(vm) {
256+
format!("LP_{}", s)
257+
} else {
258+
"LP_unknown".to_string()
259+
};
260+
261+
// Create a new type that inherits from _Pointer
262+
let type_type = &vm.ctx.types.type_type;
263+
let bases = vm.ctx.new_tuple(vec![pointer_base]);
264+
let dict = vm.ctx.new_dict();
265+
dict.set_item("_type_", cls.clone(), vm)?;
266+
267+
let new_type = type_type
268+
.as_object()
269+
.call((vm.ctx.new_str(name), bases, dict), vm)?;
270+
271+
// Store in cache using __setitem__
272+
vm.call_method(&cache, "__setitem__", (cls, new_type.clone()))?;
273+
274+
Ok(new_type)
275+
}
224276

225277
#[pyfunction(name = "pointer")]
226-
pub fn pointer_fn(_inst: PyObjectRef) {}
278+
pub fn create_pointer_inst(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
279+
// Get the type of the object
280+
let obj_type = obj.class().to_owned();
281+
282+
// Create pointer type for this object's type
283+
let ptr_type = create_pointer_type(obj_type.into(), vm)?;
284+
285+
// Create an instance of the pointer type with the object
286+
ptr_type.call((obj,), vm)
287+
}
227288

228289
#[pyfunction]
229290
fn _pointer_type_cache() -> PyObjectRef {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ impl PyCSimpleType {
171171
.clone(),
172172
))
173173
}
174+
175+
#[pyclassmethod]
176+
fn from_param(cls: PyTypeRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
177+
// If the value is already an instance of the requested type, return it
178+
if value.fast_isinstance(&cls) {
179+
return Ok(value);
180+
}
181+
182+
// Check for _as_parameter_ attribute
183+
if let Ok(as_parameter) = value.get_attr("_as_parameter_", vm) {
184+
return PyCSimpleType::from_param(cls, as_parameter, vm);
185+
}
186+
187+
Err(vm.new_type_error("wrong type".to_string()))
188+
}
174189
}
175190

176191
#[pyclass(

0 commit comments

Comments
 (0)