FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Initial _ctypes implementation by arihant2math · Pull Request #5519 · RustPython/RustPython · GitHub

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .lock  (1) .py  (1) .rs  (3) .toml  (1) All 4 file types selected
Only manifest files
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 105 additions & 0 deletions extra_tests/snippets/builtins_ctypes.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from _ctypes import sizeof
from _ctypes import _SimpleCData
from struct import calcsize as _calcsize

def _check_size(typ, typecode=None):
# Check if sizeof(ctypes_type) against struct.calcsize. This
# should protect somewhat against a misconfigured libffi.
from struct import calcsize
if typecode is None:
# Most _type_ codes are the same as used in struct
typecode = typ._type_
actual, required = sizeof(typ), calcsize(typecode)
if actual != required:
raise SystemError("sizeof(%s) wrong: %d instead of %d" % \
(typ, actual, required))

class c_short(_SimpleCData):
_type_ = "h"
_check_size(c_short)

class c_ushort(_SimpleCData):
_type_ = "H"
_check_size(c_ushort)

class c_long(_SimpleCData):
_type_ = "l"
_check_size(c_long)

class c_ulong(_SimpleCData):
_type_ = "L"
_check_size(c_ulong)

if _calcsize("i") == _calcsize("l"):
# if int and long have the same size, make c_int an alias for c_long
c_int = c_long
c_uint = c_ulong
else:
class c_int(_SimpleCData):
_type_ = "i"
_check_size(c_int)

class c_uint(_SimpleCData):
_type_ = "I"
_check_size(c_uint)

class c_float(_SimpleCData):
_type_ = "f"
_check_size(c_float)

class c_double(_SimpleCData):
_type_ = "d"
_check_size(c_double)

class c_longdouble(_SimpleCData):
_type_ = "g"
if sizeof(c_longdouble) == sizeof(c_double):
c_longdouble = c_double

if _calcsize("l") == _calcsize("q"):
# if long and long long have the same size, make c_longlong an alias for c_long
c_longlong = c_long
c_ulonglong = c_ulong
else:
class c_longlong(_SimpleCData):
_type_ = "q"
_check_size(c_longlong)

class c_ulonglong(_SimpleCData):
_type_ = "Q"
## def from_param(cls, val):
## return ('d', float(val), val)
## from_param = classmethod(from_param)
_check_size(c_ulonglong)

class c_ubyte(_SimpleCData):
_type_ = "B"
c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
# backward compatibility:
##c_uchar = c_ubyte
_check_size(c_ubyte)

class c_byte(_SimpleCData):
_type_ = "b"
c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
_check_size(c_byte)

class c_char(_SimpleCData):
_type_ = "c"
c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
_check_size(c_char)

class c_char_p(_SimpleCData):
_type_ = "z"
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, c_void_p.from_buffer(self).value)
_check_size(c_char_p, "P")

class c_void_p(_SimpleCData):
_type_ = "P"
c_voidp = c_void_p # backwards compatibility (to a bug)
_check_size(c_void_p)

class c_bool(_SimpleCData):
_type_ = "?"
_check_size(c_bool)
3 changes: 2 additions & 1 deletion vm/Cargo.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,15 @@ uname = "0.1.1"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
rustyline = { workspace = true }
which = "6"
errno = "0.3"
widestring = { workspace = true }

[target.'cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))'.dependencies]
num_cpus = "1.13.1"

[target.'cfg(windows)'.dependencies]
junction = { workspace = true }
schannel = { workspace = true }
widestring = { workspace = true }
winreg = "0.52"

[target.'cfg(windows)'.dependencies.windows]
Expand Down
107 changes: 107 additions & 0 deletions vm/src/stdlib/ctypes.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
pub(crate) mod base;

use crate::builtins::PyModule;
use crate::{PyRef, VirtualMachine};

pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
let module = _ctypes::make_module(vm);
base::extend_module_nodes(vm, &module);
module
}

#[pymodule]
pub(crate) mod _ctypes {
use super::base::PyCSimple;
use crate::builtins::PyTypeRef;
use crate::class::StaticType;
use crate::function::Either;
use crate::{AsObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine};
use crossbeam_utils::atomic::AtomicCell;
use std::ffi::{
c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong,
c_ulonglong,
};
use std::mem;
use widestring::WideChar;

pub fn get_size(ty: &str) -> usize {
match ty {
"u" => mem::size_of::<WideChar>(),
"c" | "b" => mem::size_of::<c_schar>(),
"h" => mem::size_of::<c_short>(),
"H" => mem::size_of::<c_short>(),
"i" => mem::size_of::<c_int>(),
"I" => mem::size_of::<c_uint>(),
"l" => mem::size_of::<c_long>(),
"q" => mem::size_of::<c_longlong>(),
"L" => mem::size_of::<c_ulong>(),
"Q" => mem::size_of::<c_ulonglong>(),
"f" => mem::size_of::<c_float>(),
"d" | "g" => mem::size_of::<c_double>(),
"?" | "B" => mem::size_of::<c_uchar>(),
"P" | "z" | "Z" => mem::size_of::<usize>(),
_ => unreachable!(),
}
}

const SIMPLE_TYPE_CHARS: &str = "cbBhHiIlLdfguzZPqQ?";

pub fn new_simple_type(
cls: Either<&PyObjectRef, &PyTypeRef>,
vm: &VirtualMachine,
) -> PyResult<PyCSimple> {
let cls = match cls {
Either::A(obj) => obj,
Either::B(typ) => typ.as_object(),
};

if let Ok(_type_) = cls.get_attr("_type_", vm) {
if _type_.is_instance((&vm.ctx.types.str_type).as_ref(), vm)? {
let tp_str = _type_.str(vm)?.to_string();

if tp_str.len() != 1 {
Err(vm.new_value_error(
format!("class must define a '_type_' attribute which must be a string of length 1, str: {tp_str}"),
))
} else if !SIMPLE_TYPE_CHARS.contains(tp_str.as_str()) {
Err(vm.new_attribute_error(format!("class must define a '_type_' attribute which must be\n a single character string containing one of {SIMPLE_TYPE_CHARS}, currently it is {tp_str}.")))
} else {
Ok(PyCSimple {
_type_: tp_str,
_value: AtomicCell::new(vm.ctx.none()),
})
}
} else {
Err(vm.new_type_error("class must define a '_type_' string attribute".to_string()))
}
} else {
Err(vm.new_attribute_error("class must define a '_type_' attribute".to_string()))
}
}

#[pyfunction(name = "sizeof")]
pub fn size_of(tp: Either<PyTypeRef, PyObjectRef>, vm: &VirtualMachine) -> PyResult<usize> {
match tp {
Either::A(type_) if type_.fast_issubclass(PyCSimple::static_type()) => {
let zelf = new_simple_type(Either::B(&type_), vm)?;
Ok(get_size(zelf._type_.as_str()))
}
Either::B(obj) if obj.has_attr("size_of_instances", vm)? => {
let size_of_method = obj.get_attr("size_of_instances", vm)?;
let size_of_return = size_of_method.call(vec![], vm)?;
Ok(usize::try_from_object(vm, size_of_return)?)
}
_ => Err(vm.new_type_error("this type has no size".to_string())),
}
}

#[pyfunction]
fn get_errno() -> i32 {
errno::errno().0
}

#[pyfunction]
fn set_errno(value: i32) {
errno::set_errno(errno::Errno(value));
}
}
Loading

Back | FazBrowse Home | New Git URL