Skip to content

_ctypes pt. 5 #5653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions extra_tests/snippets/stdlib_ctypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def create_string_buffer(init, size=None):
size = len(init)+1
_sys.audit("ctypes.create_string_buffer", init, size)
buftype = c_char.__mul__(size)
print(type(c_char.__mul__(size)))
# buftype = c_char * size
buf = buftype()
buf.value = init
Expand Down Expand Up @@ -269,8 +268,14 @@ def LoadLibrary(self, name):
test_byte_array = create_string_buffer(b"Hello, World!\n")
assert test_byte_array._length_ == 15

if _os.name == "posix" or _sys.platform == "darwin":
pass
if _os.name == "posix":
if _sys.platform == "darwin":
libc = cdll.LoadLibrary("libc.dylib")
libc.rand()
i = c_int(1)
print("start srand")
print(libc.srand(i))
print(test_byte_array)
else:
import os

Expand Down
11 changes: 10 additions & 1 deletion vm/src/stdlib/ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

pub(crate) mod array;
pub(crate) mod base;
pub(crate) mod field;
pub(crate) mod function;
pub(crate) mod library;
pub(crate) mod pointer;
pub(crate) mod structure;
pub(crate) mod thunk;
pub(crate) mod union;
pub(crate) mod util;

use crate::builtins::PyModule;
use crate::class::PyClassImpl;
Expand All @@ -17,14 +20,18 @@ pub fn extend_module_nodes(vm: &VirtualMachine, module: &Py<PyModule>) {
let ctx = &vm.ctx;
PyCSimpleType::make_class(ctx);
array::PyCArrayType::make_class(ctx);
field::PyCFieldType::make_class(ctx);
pointer::PyCPointerType::make_class(ctx);
extend_module!(vm, module, {
"_CData" => PyCData::make_class(ctx),
"_SimpleCData" => PyCSimple::make_class(ctx),
"Array" => array::PyCArray::make_class(ctx),
"CField" => field::PyCField::make_class(ctx),
"CFuncPtr" => function::PyCFuncPtr::make_class(ctx),
"_Pointer" => pointer::PyCPointer::make_class(ctx),
"_pointer_type_cache" => ctx.new_dict(),
"Structure" => structure::PyCStructure::make_class(ctx),
"CThunkObject" => thunk::PyCThunk::make_class(ctx),
"Union" => union::PyCUnion::make_class(ctx),
})
}
Expand Down Expand Up @@ -207,7 +214,9 @@ pub(crate) mod _ctypes {
// TODO: load_flags
let cache = library::libcache();
let mut cache_write = cache.write();
let (id, _) = cache_write.get_or_insert_lib(&name, vm).unwrap();
let (id, _) = cache_write
.get_or_insert_lib(&name, vm)
.map_err(|e| vm.new_os_error(e.to_string()))?;
Ok(id)
}

Expand Down
1 change: 1 addition & 0 deletions vm/src/stdlib/ctypes/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ impl PyCArray {
}

impl PyCArray {
#[allow(unused)]
pub fn to_arg(&self, _vm: &VirtualMachine) -> PyResult<libffi::middle::Arg> {
let value = self.value.read();
let py_bytes = value.payload::<PyBytes>().unwrap();
Expand Down
20 changes: 10 additions & 10 deletions vm/src/stdlib/ctypes/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,24 +278,24 @@ impl PyCSimple {
let value = unsafe { (*self.value.as_ptr()).clone() };
if let Ok(i) = value.try_int(vm) {
let i = i.as_bigint();
if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u8().as_raw_ptr()) {
return i.to_u8().map(|r: u8| libffi::middle::Arg::new(&r));
return if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u8().as_raw_ptr()) {
i.to_u8().map(|r: u8| libffi::middle::Arg::new(&r))
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i8().as_raw_ptr()) {
return i.to_i8().map(|r: i8| libffi::middle::Arg::new(&r));
i.to_i8().map(|r: i8| libffi::middle::Arg::new(&r))
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u16().as_raw_ptr()) {
return i.to_u16().map(|r: u16| libffi::middle::Arg::new(&r));
i.to_u16().map(|r: u16| libffi::middle::Arg::new(&r))
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i16().as_raw_ptr()) {
return i.to_i16().map(|r: i16| libffi::middle::Arg::new(&r));
i.to_i16().map(|r: i16| libffi::middle::Arg::new(&r))
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u32().as_raw_ptr()) {
return i.to_u32().map(|r: u32| libffi::middle::Arg::new(&r));
i.to_u32().map(|r: u32| libffi::middle::Arg::new(&r))
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i32().as_raw_ptr()) {
return i.to_i32().map(|r: i32| libffi::middle::Arg::new(&r));
i.to_i32().map(|r: i32| libffi::middle::Arg::new(&r))
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::u64().as_raw_ptr()) {
return i.to_u64().map(|r: u64| libffi::middle::Arg::new(&r));
i.to_u64().map(|r: u64| libffi::middle::Arg::new(&r))
} else if std::ptr::eq(ty.as_raw_ptr(), libffi::middle::Type::i64().as_raw_ptr()) {
return i.to_i64().map(|r: i64| libffi::middle::Arg::new(&r));
i.to_i64().map(|r: i64| libffi::middle::Arg::new(&r))
} else {
return None;
None
}
}
if let Ok(_f) = value.try_float(vm) {
Expand Down
134 changes: 134 additions & 0 deletions vm/src/stdlib/ctypes/field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use crate::builtins::PyType;
use crate::builtins::PyTypeRef;
use crate::stdlib::ctypes::PyCData;
use crate::types::Constructor;
use crate::types::Representable;
use crate::{Py, PyResult, VirtualMachine};

#[pyclass(name = "PyCFieldType", base = "PyType", module = "_ctypes")]
#[derive(PyPayload, Debug)]
pub struct PyCFieldType {
pub(super) inner: PyCField,
}

#[pyclass]
impl PyCFieldType {}

#[pyclass(
name = "CField",
base = "PyCData",
metaclass = "PyCFieldType",
module = "_ctypes"
)]
#[derive(Debug, PyPayload)]
pub struct PyCField {
byte_offset: usize,
byte_size: usize,
#[allow(unused)]
index: usize,
proto: PyTypeRef,
anonymous: bool,
bitfield_size: bool,
bit_offset: u8,
name: String,
}

impl Representable for PyCField {
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
let tp_name = zelf.proto.name().to_string();
if zelf.bitfield_size != false {
Ok(format!(
"<{} type={}, ofs={byte_offset}, bit_size={bitfield_size}, bit_offset={bit_offset}",
zelf.name,
tp_name,
byte_offset = zelf.byte_offset,
bitfield_size = zelf.bitfield_size,
bit_offset = zelf.bit_offset
))
} else {
Ok(format!(
"<{} type={tp_name}, ofs={}, size={}",
zelf.name, zelf.byte_offset, zelf.byte_size
))
}
}
}

#[derive(Debug, FromArgs)]
pub struct PyCFieldConstructorArgs {
// PyObject *name, PyObject *proto,
// Py_ssize_t byte_size, Py_ssize_t byte_offset,
// Py_ssize_t index, int _internal_use,
// PyObject *bit_size_obj, PyObject *bit_offset_obj
}

impl Constructor for PyCField {
type Args = PyCFieldConstructorArgs;

fn py_new(_cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
Err(vm.new_type_error("Cannot instantiate a PyCField".to_string()))
}
}

#[pyclass(flags(BASETYPE, IMMUTABLETYPE), with(Constructor, Representable))]
impl PyCField {
#[pygetset]
fn size(&self) -> usize {
self.byte_size
}

#[pygetset]
fn bit_size(&self) -> bool {
self.bitfield_size
}

#[pygetset]
fn is_bitfield(&self) -> bool {
self.bitfield_size
}

#[pygetset]
fn is_anonymous(&self) -> bool {
self.anonymous
}

#[pygetset]
fn name(&self) -> String {
self.name.clone()
}

#[pygetset(name = "type")]
fn type_(&self) -> PyTypeRef {
self.proto.clone()
}

#[pygetset]
fn offset(&self) -> usize {
self.byte_offset
}

#[pygetset]
fn byte_offset(&self) -> usize {
self.byte_offset
}

#[pygetset]
fn byte_size(&self) -> usize {
self.byte_size
}

#[pygetset]
fn bit_offset(&self) -> u8 {
self.bit_offset
}
}

#[inline(always)]
pub const fn low_bit(offset: usize) -> usize {
offset & 0xFFFF
}

#[inline(always)]
pub const fn high_bit(offset: usize) -> usize {
offset >> 16
}
Loading
Loading