diff --git a/Cargo.toml b/Cargo.toml index 651d492e..88ddb87c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,10 +32,16 @@ backtrace = "0.3" regex = "0.2" [features] -default = ["nightly"] +default = [] + +# Use this feature when building python2 binding. +python2 = [] + +# Use this feature when building python3 binding. +python3 = [] # Enable additional features that require nightly rust -nightly = [] +#nightly = [] # Use this feature when building an extension module. # It tells the linker to keep the python symbols unresolved, diff --git a/build.rs b/build.rs index 8f64b5ce..3b282f42 100644 --- a/build.rs +++ b/build.rs @@ -13,6 +13,13 @@ struct PythonVersion { minor: Option } +impl PartialEq for PythonVersion { + + fn eq(&self, o: &PythonVersion) -> bool { + self.major == o.major && (self.minor.is_none() || self.minor == o.minor) + } +} + impl fmt::Display for PythonVersion { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { try!(self.major.fmt(f)); @@ -25,7 +32,7 @@ impl fmt::Display for PythonVersion { } } -const MIN_MINOR: u8 = 5; +const PY3_MIN_MINOR: u8 = 5; const CFG_KEY: &'static str = "py_sys_config"; @@ -191,7 +198,9 @@ fn run_python_script(interpreter: &str, script: &str) -> Result #[cfg(not(target_os="macos"))] #[cfg(not(target_os="windows"))] -fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, enable_shared: bool) -> Result { +fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, enable_shared: bool) + -> Result +{ if enable_shared { Ok(format!("cargo:rustc-link-lib=python{}", ld_version)) } else { @@ -200,14 +209,16 @@ fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, enable_shared: bool) } #[cfg(target_os="macos")] -fn get_macos_linkmodel() -> Result { +fn get_macos_linkmodel() -> Result +{ let script = "import sysconfig; print('framework' if sysconfig.get_config_var('PYTHONFRAMEWORK') else ('shared' if sysconfig.get_config_var('Py_ENABLE_SHARED') else 'static'));"; let out = run_python_script("python", script).unwrap(); Ok(out.trim_right().to_owned()) } #[cfg(target_os="macos")] -fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, _: bool) -> Result { +fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, _: bool) -> Result +{ // os x can be linked to a framework or static or dynamic, and // Py_ENABLE_SHARED is wrong; framework means shared library match get_macos_linkmodel().unwrap().as_ref() { @@ -222,7 +233,8 @@ fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, _: bool) -> Result Result { +fn get_interpreter_version(line: &str) -> Result +{ let version_re = Regex::new(r"\((\d+), (\d+)\)").unwrap(); match version_re.captures(&line) { Some(cap) => Ok(PythonVersion { @@ -235,7 +247,8 @@ fn get_interpreter_version(line: &str) -> Result { } #[cfg(target_os="windows")] -fn get_rustc_link_lib(version: &PythonVersion, _: &str, _: bool) -> Result { +fn get_rustc_link_lib(version: &PythonVersion, _: &str, _: bool) -> Result +{ // Py_ENABLE_SHARED doesn't seem to be present on windows. Ok(format!("cargo:rustc-link-lib=pythonXY:python{}{}", version.major, match version.minor { @@ -250,29 +263,41 @@ fn get_rustc_link_lib(version: &PythonVersion, _: &str, _: bool) -> Result Result<(PythonVersion, String, Vec), String> +fn find_interpreter_and_get_config(expected_version: &PythonVersion) + -> Result<(PythonVersion, String, Vec), String> { if let Some(sys_executable) = env::var_os("PYTHON_SYS_EXECUTABLE") { let interpreter_path = sys_executable.to_str() .expect("Unable to get PYTHON_SYS_EXECUTABLE value"); let (interpreter_version, lines) = try!(get_config_from_interpreter(interpreter_path)); - if interpreter_version.major < 3 || MIN_MINOR > interpreter_version.minor.unwrap_or(0) { - return Err(format!("Unsupported python version in PYTHON_SYS_EXECUTABLE={}\n\ - \tmin version 3.4 != found {}", - interpreter_path, - interpreter_version)); - } else { + if expected_version == &interpreter_version { return Ok((interpreter_version, interpreter_path.to_owned(), lines)); + } else { + return Err(format!("Unsupported python version in PYTHON_SYS_EXECUTABLE={}\n\ + \tmin version {} != found {}", + interpreter_path, expected_version, interpreter_version)); } } + // check default python + let interpreter_path = "python"; + let (interpreter_version, lines) = try!(get_config_from_interpreter(interpreter_path)); + if expected_version == &interpreter_version { + return Ok((interpreter_version, interpreter_path.to_owned(), lines)); + } - { - let interpreter_path = "python3"; - let (interpreter_version, lines) = try!(get_config_from_interpreter(interpreter_path)); - if MIN_MINOR <= interpreter_version.minor.unwrap_or(0) && - interpreter_version.major == 3 { - return Ok((interpreter_version, interpreter_path.to_owned(), lines)); + let major_interpreter_path = &format!("python{}", expected_version.major); + let (interpreter_version, lines) = try!(get_config_from_interpreter(major_interpreter_path)); + if expected_version == &interpreter_version { + return Ok((interpreter_version, major_interpreter_path.to_owned(), lines)); + } + + if let Some(minor) = expected_version.minor { + let minor_interpreter_path = &format!("python{}.{}", expected_version.major, minor); + let (interpreter_version, lines) = try!(get_config_from_interpreter( + minor_interpreter_path)); + if expected_version == &interpreter_version { + return Ok((interpreter_version, minor_interpreter_path.to_owned(), lines)); } } @@ -296,10 +321,10 @@ print(sys.exec_prefix);"; /// cargo vars to stdout. /// /// Note that if the python doesn't satisfy expected_version, this will error. -fn configure_from_path() -> Result<(String, String), String> { +fn configure_from_path(expected_version: &PythonVersion) -> Result<(String, String), String> { let (interpreter_version, interpreter_path, lines) = try!( - find_interpreter_and_get_config()); + find_interpreter_and_get_config(expected_version)); let libpath: &str = &lines[1]; let enable_shared: &str = &lines[2]; @@ -324,15 +349,50 @@ fn configure_from_path() -> Result<(String, String), String> { println!("cargo:rustc-cfg=Py_LIMITED_API"); } if let Some(minor) = some_minor { - for i in 4..(minor+1) { + if minor < PY3_MIN_MINOR { + return Err(format!("Python 3 min version is 3.{}", minor)) + } + for i in 5..(minor+1) { println!("cargo:rustc-cfg=Py_3_{}", i); flags += format!("CFG_Py_3_{},", i).as_ref(); } + println!("cargo:rustc-cfg=Py_3"); } + } else { + println!("cargo:rustc-cfg=Py_2"); + flags += format!("CFG_Py_2,").as_ref(); } return Ok((interpreter_path, flags)); } +/// Determine the python version we're supposed to be building +/// from the features passed via the environment. +/// +/// The environment variable can choose to omit a minor +/// version if the user doesn't care. +fn version_from_env() -> Result { + let re = Regex::new(r"CARGO_FEATURE_PYTHON(\d+)(_(\d+))?").unwrap(); + // sort env::vars so we get more explicit version specifiers first + // so if the user passes e.g. the python-3 feature and the python-3-5 + // feature, python-3-5 takes priority. + let mut vars = env::vars().collect::>(); + vars.sort_by(|a, b| b.cmp(a)); + for (key, _) in vars { + match re.captures(&key) { + Some(cap) => return Ok(PythonVersion { + major: cap.get(1).unwrap().as_str().parse().unwrap(), + minor: match cap.get(3) { + Some(s) => Some(s.as_str().parse().unwrap()), + None => None + } + }), + None => () + } + } + + Err("Python version feature was not found. At least one python version \ + feature must be enabled.".to_owned()) +} fn main() { // 1. Setup cfg variables so we can do conditional compilation in this @@ -345,7 +405,11 @@ fn main() { // If you have troubles with your shell accepting '.' in a var name, // try using 'env' (sorry but this isn't our fault - it just has to // match the pkg-config package name, which is going to have a . in it). - let (python_interpreter_path, flags) = configure_from_path().unwrap(); + let version = match version_from_env() { + Ok(v) => v, + Err(_) => PythonVersion{major: 3, minor: None} + }; + let (python_interpreter_path, flags) = configure_from_path(&version).unwrap(); let config_map = get_config_vars(&python_interpreter_path).unwrap(); for (key, val) in &config_map { match cfg_line_for_var(key, val) { diff --git a/pyo3cls/src/lib.rs b/pyo3cls/src/lib.rs index 9d71c623..c9556df7 100644 --- a/pyo3cls/src/lib.rs +++ b/pyo3cls/src/lib.rs @@ -21,9 +21,38 @@ mod py_ptr; mod defs; mod func; mod method; +mod module; mod utils; +#[proc_macro_attribute] +pub fn mod2init(attr: TokenStream, input: TokenStream) -> TokenStream { + // Construct a string representation of the type definition + let source = input.to_string(); + + // Parse the string representation into a syntax tree + let mut ast = syn::parse_item(&source).unwrap(); + + // Build the output + let init = module::build_py2_module_init(&mut ast, attr.to_string()); + + TokenStream::from_str(init.as_str()).unwrap() +} + +#[proc_macro_attribute] +pub fn mod3init(attr: TokenStream, input: TokenStream) -> TokenStream { + // Construct a string representation of the type definition + let source = input.to_string(); + + // Parse the string representation into a syntax tree + let mut ast = syn::parse_item(&source).unwrap(); + + // Build the output + let init = module::build_py3_module_init(&mut ast, attr.to_string()); + + TokenStream::from_str(init.as_str()).unwrap() +} + #[proc_macro_attribute] pub fn proto(_: TokenStream, input: TokenStream) -> TokenStream { // Construct a string representation of the type definition diff --git a/pyo3cls/src/module.rs b/pyo3cls/src/module.rs new file mode 100644 index 00000000..3279db17 --- /dev/null +++ b/pyo3cls/src/module.rs @@ -0,0 +1,136 @@ +// Copyright (c) 2017-present PyO3 Project and Contributors + +use syn; +use quote::Tokens; + + +pub fn build_py3_module_init(ast: &mut syn::Item, attr: String) -> Tokens { + let modname = &attr.to_string()[1..attr.to_string().len()-1].to_string(); + let name = syn::Ident::from(modname.as_ref()); + + println!("MOD: {:?}", modname); + + let tokens = match ast.node { + syn::ItemKind::Fn(_, _, _, _, _, _) => { + py3_init(&ast.ident, &name); + }, + _ => panic!("#[modinit] can only be used with fn block"), + }; + + let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_MODINIT_{}", modname.trim())); + + quote! { + #[feature(specialization)] + #[allow(non_upper_case_globals, unused_attributes, + unused_qualifications, unused_variables, non_camel_case_types)] + const #dummy_const: () = { + use std; + extern crate pyo3 as _pyo3; + + #tokens + }; + } +} + +pub fn py3_init(fnname: &syn::Ident, name: &syn::Ident) -> Tokens { + quote! { + #[no_mangle] + #[allow(non_snake_case)] + pub unsafe extern "C" fn PyInit_#name() -> *mut _pyo3::ffi::PyObject { + static mut MODULE_DEF: $crate::ffi::PyModuleDef = $crate::ffi::PyModuleDef_INIT; + // We can't convert &'static str to *const c_char within a static initializer, + // so we'll do it here in the module initialization: + MODULE_DEF.m_name = concat!(stringify!($name), "\0").as_ptr() as *const _; + + let guard = _pyo3::callback::AbortOnDrop("py_module_init"); + let py = _pyo3::Python::assume_gil_acquired(); + _pyo3::ffi::PyEval_InitThreads(); + let module = _pyo3::ffi::PyModule_Create(def); + if module.is_null() { + mem::forget(guard); + return module; + } + + let module = match _pyo3::PyObject::from_owned_ptr( + py, module).cast_into::(py) + { + Ok(m) => m, + Err(e) => { + _pyo3::PyErr::from(e).restore(py); + mem::forget(guard); + return ptr::null_mut(); + } + }; + let ret = match #fnname(py, &module) { + Ok(()) => module.into_ptr(), + Err(e) => { + e.restore(py); + ptr::null_mut() + } + }; + mem::forget(guard); + ret + } + } +} + +pub fn build_py2_module_init(ast: &mut syn::Item, attr: String) -> Tokens { + let modname = &attr.to_string()[1..attr.to_string().len()-1].to_string(); + let name = syn::Ident::from(modname.as_ref()); + + let tokens = match ast.node { + syn::ItemKind::Fn(_, _, _, _, _, _) => { + py2_init(&ast.ident, &name); + }, + _ => panic!("#[modinit] can only be used with fn block"), + }; + + let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_MODINIT_{}", modname.trim())); + + quote! { + #[feature(specialization)] + #[allow(non_upper_case_globals, unused_attributes, + unused_qualifications, unused_variables, non_camel_case_types)] + const #dummy_const: () = { + use std; + extern crate pyo3 as _pyo3; + + #tokens + }; + } +} + +pub fn py2_init(fnname: &syn::Ident, name: &syn::Ident) -> Tokens { + quote! { + #[no_mangle] + #[allow(non_snake_case)] + pub unsafe extern "C" fn init#name() -> *mut _pyo3::ffi::PyObject { + use pyo3::ffi; + + let name = concat!(stringify!($name), "\0").as_ptr() as *const _; + let guard = function::AbortOnDrop("py_module_initializer"); + let py = Python::assume_gil_acquired(); + ffi::PyEval_InitThreads(); + let module = ffi::Py_InitModule(name, ptr::null_mut()); + if module.is_null() { + mem::forget(guard); + return; + } + + let module = match PyObject::from_borrowed_ptr(py, module).cast_into::(py) { + Ok(m) => m, + Err(e) => { + _pyo3::PyErr::from(e).restore(py); + mem::forget(guard); + return; + } + }; + let ret = match #fnname(py, &module) { + Ok(()) => (), + Err(e) => e.restore(py) + }; + mem::forget(guard); + ret + } + } +} diff --git a/src/class/async.rs b/src/class/async.rs index 6c545777..7a818e5e 100644 --- a/src/class/async.rs +++ b/src/class/async.rs @@ -68,6 +68,7 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> { } +#[cfg(Py_3)] #[doc(hidden)] pub trait PyAsyncProtocolImpl { fn tp_as_async() -> Option; @@ -75,6 +76,7 @@ pub trait PyAsyncProtocolImpl { fn methods() -> Vec; } +#[cfg(Py_3)] impl PyAsyncProtocolImpl for T { #[inline] default fn tp_as_async() -> Option { @@ -87,6 +89,7 @@ impl PyAsyncProtocolImpl for T { } } +#[cfg(Py_3)] impl<'p, T> PyAsyncProtocolImpl for T where T: PyAsyncProtocol<'p> { #[inline] fn tp_as_async() -> Option { diff --git a/src/class/basic.rs b/src/class/basic.rs index 402ca6fd..5c352da6 100644 --- a/src/class/basic.rs +++ b/src/class/basic.rs @@ -296,12 +296,12 @@ impl<'p, T> PyObjectHashProtocolImpl for T where T: PyObjectProtocol<'p> None } } -impl PyObjectHashProtocolImpl for T where T: for<'p> PyObjectHashProtocol<'p> + ToInstancePtr +impl PyObjectHashProtocolImpl for T + where T: for<'p> PyObjectHashProtocol<'p> + ToInstancePtr { #[inline] fn tp_hash() -> Option { - py_unary_func!(PyObjectHashProtocol, - T::__hash__, usize, HashConverter, ffi::Py_hash_t) + py_unary_func!(PyObjectHashProtocol, T::__hash__, usize, HashConverter, ffi::Py_hash_t) } } diff --git a/src/class/buffer.rs b/src/class/buffer.rs index 565d0f91..161a758c 100644 --- a/src/class/buffer.rs +++ b/src/class/buffer.rs @@ -52,6 +52,7 @@ impl<'p, T> PyBufferProtocolImpl for T where T: PyBufferProtocol<'p> + ToInstanc Some(ffi::PyBufferProcs{ bf_getbuffer: Self::cb_bf_getbuffer(), bf_releasebuffer: None, + .. ffi::PyBufferProcs_INIT }) } } diff --git a/src/class/macros.rs b/src/class/macros.rs index bb7796e8..78ef30e6 100644 --- a/src/class/macros.rs +++ b/src/class/macros.rs @@ -277,14 +277,13 @@ macro_rules! py_func_set{ const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()"); $crate::callback::cb_unary_unit::(LOCATION, slf, |py, slf| { if value.is_null() { - let e = PyErr::new::( - py, format!("Subscript deletion not supported by {:?}", - stringify!(T))); + let e = $crate::PyErr::new::( + py, format!("Subscript deletion not supported by {:?}", stringify!(T))); e.restore(py); -1 } else { - let name = ::PyObject::from_borrowed_ptr(py, name); - let value = ::PyObject::from_borrowed_ptr(py, value); + let name = $crate::PyObject::from_borrowed_ptr(py, name); + let value = $crate::PyObject::from_borrowed_ptr(py, value); let result = match name.extract(py) { Ok(name) => match value.extract(py) { Ok(value) => { diff --git a/src/class/mod.rs b/src/class/mod.rs index 9a684862..94e8b40c 100644 --- a/src/class/mod.rs +++ b/src/class/mod.rs @@ -29,7 +29,6 @@ pub use self::methods::{PyMethodDef, PyMethodDefType, PyMethodType, PyGetterDef, PySetterDef}; use ffi; -use typeob::PyTypeInfo; #[derive(Debug)] pub enum CompareOp { @@ -40,5 +39,3 @@ pub enum CompareOp { Gt = ffi::Py_GT as isize, Ge = ffi::Py_GE as isize } - -pub trait PyCustomObject : PyTypeInfo + Sized {} diff --git a/src/class/number.rs b/src/class/number.rs index 7e528d73..c2b63593 100644 --- a/src/class/number.rs +++ b/src/class/number.rs @@ -10,7 +10,7 @@ use callback::PyObjectCallbackConverter; use typeob::PyTypeInfo; use class::methods::PyMethodDef; use class::basic::PyObjectProtocolImpl; -use ::{c_void, IntoPyObject, FromPyObject, ToInstancePtr}; +use ::{IntoPyObject, FromPyObject, ToInstancePtr}; /// Number interface #[allow(unused_variables)] @@ -372,6 +372,7 @@ pub trait PyNumberProtocolImpl { } impl<'p, T> PyNumberProtocolImpl for T { + #[cfg(Py_3)] default fn tp_as_number() -> Option { if let Some(nb_bool) = ::nb_bool_fn() { let meth = ffi::PyNumberMethods { @@ -384,14 +385,30 @@ impl<'p, T> PyNumberProtocolImpl for T { None } } + #[cfg(not(Py_3))] + default fn tp_as_number() -> Option { + if let Some(nb_bool) = ::nb_bool_fn() { + let meth = ffi::PyNumberMethods { + nb_nonzero: Some(nb_bool), + .. + ffi::PyNumberMethods_INIT + }; + Some(meth) + } else { + None + } + } default fn methods() -> Vec { Vec::new() } } impl<'p, T> PyNumberProtocolImpl for T where T: PyNumberProtocol<'p> { + #[cfg(Py_3)] #[inline] fn tp_as_number() -> Option { + use std::os::raw::c_void; + Some(ffi::PyNumberMethods { nb_add: Self::nb_add(), nb_subtract: Self::nb_subtract(), @@ -431,6 +448,51 @@ impl<'p, T> PyNumberProtocolImpl for T where T: PyNumberProtocol<'p> { nb_inplace_matrix_multiply: Self::nb_inplace_matrix_multiply(), }) } + #[cfg(not(Py_3))] + #[inline] + fn tp_as_number() -> Option { + Some(ffi::PyNumberMethods { + nb_add: Self::nb_add(), + nb_subtract: Self::nb_subtract(), + nb_multiply: Self::nb_multiply(), + nb_remainder: Self::nb_remainder(), + nb_divmod: Self::nb_divmod(), + nb_power: Self::nb_power(), + nb_negative: Self::nb_negative(), + nb_positive: Self::nb_positive(), + nb_absolute: Self::nb_absolute(), + nb_nonzero: ::nb_bool_fn(), + nb_invert: Self::nb_invert(), + nb_lshift: Self::nb_lshift(), + nb_rshift: Self::nb_rshift(), + nb_and: Self::nb_and(), + nb_xor: Self::nb_xor(), + nb_or: Self::nb_or(), + nb_c_int: Self::nb_int(), + nb_float: Self::nb_float(), + nb_inplace_add: Self::nb_inplace_add(), + nb_inplace_subtract: Self::nb_inplace_subtract(), + nb_inplace_multiply: Self::nb_inplace_multiply(), + nb_inplace_remainder: Self::nb_inplace_remainder(), + nb_inplace_power: Self::nb_inplace_power(), + nb_inplace_lshift: Self::nb_inplace_lshift(), + nb_inplace_rshift: Self::nb_inplace_rshift(), + nb_inplace_and: Self::nb_inplace_and(), + nb_inplace_xor: Self::nb_inplace_xor(), + nb_inplace_or: Self::nb_inplace_or(), + nb_floor_divide: Self::nb_floor_divide(), + nb_true_divide: Self::nb_true_divide(), + nb_inplace_floor_divide: Self::nb_inplace_floor_divide(), + nb_inplace_true_divide: Self::nb_inplace_true_divide(), + nb_index: Self::nb_index(), + nb_coerce: None, + nb_divide: None, + nb_hex: None, + nb_inplace_divide: None, + nb_long: None, + nb_oct: None, + }) + } #[inline] fn methods() -> Vec { diff --git a/src/class/sequence.rs b/src/class/sequence.rs index 6c0529af..09d5ead5 100644 --- a/src/class/sequence.rs +++ b/src/class/sequence.rs @@ -106,6 +106,7 @@ impl PySequenceProtocolImpl for T { } impl<'p, T> PySequenceProtocolImpl for T where T: PySequenceProtocol<'p> { + #[cfg(Py_3)] #[inline] fn tp_as_sequence() -> Option { let f = if let Some(df) = Self::sq_del_item() { @@ -127,6 +128,28 @@ impl<'p, T> PySequenceProtocolImpl for T where T: PySequenceProtocol<'p> { sq_inplace_repeat: Self::sq_inplace_repeat(), }) } + #[cfg(not(Py_3))] + #[inline] + fn tp_as_sequence() -> Option { + let f = if let Some(df) = Self::sq_del_item() { + Some(df) + } else { + Self::sq_ass_item() + }; + + Some(ffi::PySequenceMethods { + sq_length: Self::sq_length(), + sq_concat: Self::sq_concat(), + sq_repeat: Self::sq_repeat(), + sq_item: Self::sq_item(), + sq_slice: None, + sq_ass_item: f, + sq_ass_slice: None, + sq_contains: Self::sq_contains(), + sq_inplace_concat: Self::sq_inplace_concat(), + sq_inplace_repeat: Self::sq_inplace_repeat(), + }) + } } trait PySequenceLenProtocolImpl { diff --git a/src/err.rs b/src/err.rs index 8e62fdf6..5d2dd286 100644 --- a/src/err.rs +++ b/src/err.rs @@ -394,6 +394,7 @@ macro_rules! impl_to_pyerr { } } +#[cfg(Py_3)] /// Create `OSError` from `io::Error` impl ToPyErr for io::Error { @@ -417,6 +418,18 @@ impl ToPyErr for io::Error { } } +#[cfg(not(Py_3))] +/// Create `OSError` from `io::Error` +impl ToPyErr for io::Error { + + fn to_pyerr(&self, py: Python) -> PyErr { + let errno = self.raw_os_error().unwrap_or(0); + let errdesc = self.description(); + + PyErr::new_err(py, &py.get_type::(), (errno, errdesc)) + } +} + impl ToPyErr for std::io::IntoInnerError { fn to_pyerr(&self, py: Python) -> PyErr { PyErr::new::(py, self.description()) diff --git a/src/ffi/code.rs b/src/ffi/code.rs index 424bc35a..c9923865 100644 --- a/src/ffi/code.rs +++ b/src/ffi/code.rs @@ -94,4 +94,3 @@ pub unsafe fn PyCode_Check(op : *mut PyObject) -> c_int { pub unsafe fn PyCode_GetNumFree(op : *mut PyCodeObject) -> Py_ssize_t { ::ffi::tupleobject::PyTuple_GET_SIZE((*op).co_freevars) } - diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 9817febd..1bbad851 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -1,13 +1,6 @@ #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)] #![cfg_attr(Py_LIMITED_API, allow(unused_imports))] -// old: marked with TODO -// Based on the headers of Python 3.4.3 -// Supports the stable ABI (PEP 384) only. - -// new: -// Based on the headers of Python 3.3.0, 3.4.0 and 3.5.0. - pub use self::pyport::*; pub use self::pymem::*; @@ -71,9 +64,7 @@ pub use self::frameobject::PyFrameObject; mod pyport; // mod pymacro; contains nothing of interest for Rust - // mod pyatomic; contains nothing of interest for Rust - // mod pymath; contains nothing of interest for Rust // [cfg(not(Py_LIMITED_API))] @@ -85,7 +76,6 @@ mod object; mod objimpl; mod typeslots; mod pyhash; - mod pydebug; mod bytearrayobject; diff --git a/src/ffi/modsupport.rs b/src/ffi/modsupport.rs index c11050f6..141268e5 100644 --- a/src/ffi/modsupport.rs +++ b/src/ffi/modsupport.rs @@ -5,21 +5,16 @@ use ffi::moduleobject::PyModuleDef; use ffi::methodobject::PyMethodDef; #[cfg_attr(windows, link(name="pythonXY"))] extern "C" { - pub fn PyArg_Parse(arg1: *mut PyObject, arg2: *const c_char, ...) - -> c_int; + pub fn PyArg_Parse(arg1: *mut PyObject, arg2: *const c_char, ...) -> c_int; pub fn PyArg_ParseTuple(arg1: *mut PyObject, - arg2: *const c_char, ...) - -> c_int; + arg2: *const c_char, ...) -> c_int; pub fn PyArg_ParseTupleAndKeywords(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *const c_char, - arg4: *mut *mut c_char, ...) - -> c_int; - pub fn PyArg_ValidateKeywordArguments(arg1: *mut PyObject) - -> c_int; + arg4: *mut *mut c_char, ...) -> c_int; + pub fn PyArg_ValidateKeywordArguments(arg1: *mut PyObject) -> c_int; pub fn PyArg_UnpackTuple(arg1: *mut PyObject, arg2: *const c_char, - arg3: Py_ssize_t, arg4: Py_ssize_t, ...) - -> c_int; + arg3: Py_ssize_t, arg4: Py_ssize_t, ...) -> c_int; pub fn Py_BuildValue(arg1: *const c_char, ...) -> *mut PyObject; //pub fn _Py_BuildValue_SizeT(arg1: *const c_char, ...) // -> *mut PyObject; @@ -33,15 +28,11 @@ use ffi::methodobject::PyMethodDef; arg3: c_long) -> c_int; pub fn PyModule_AddStringConstant(arg1: *mut PyObject, arg2: *const c_char, - arg3: *const c_char) - -> c_int; + arg3: *const c_char) -> c_int; pub fn PyModule_SetDocString(arg1: *mut PyObject, - arg2: *const c_char) - -> c_int; - pub fn PyModule_AddFunctions(arg1: *mut PyObject, arg2: *mut PyMethodDef) - -> c_int; - pub fn PyModule_ExecDef(module: *mut PyObject, def: *mut PyModuleDef) - -> c_int; + arg2: *const c_char) -> c_int; + pub fn PyModule_AddFunctions(arg1: *mut PyObject, arg2: *mut PyMethodDef) -> c_int; + pub fn PyModule_ExecDef(module: *mut PyObject, def: *mut PyModuleDef) -> c_int; } pub const Py_CLEANUP_SUPPORTED: i32 = 0x20000; @@ -52,23 +43,21 @@ pub const PYTHON_ABI_VERSION: i32 = 3; #[cfg_attr(windows, link(name="pythonXY"))] extern "C" { #[cfg(not(py_sys_config="Py_TRACE_REFS"))] pub fn PyModule_Create2(module: *mut PyModuleDef, - apiver: c_int) -> *mut PyObject; + apiver: c_int) -> *mut PyObject; #[cfg(py_sys_config="Py_TRACE_REFS")] fn PyModule_Create2TraceRefs(module: *mut PyModuleDef, - apiver: c_int) -> *mut PyObject; + apiver: c_int) -> *mut PyObject; #[cfg(not(py_sys_config="Py_TRACE_REFS"))] pub fn PyModule_FromDefAndSpec2(def: *mut PyModuleDef, spec: *mut PyObject, - module_api_version: c_int) - -> *mut PyObject; + module_api_version: c_int) -> *mut PyObject; #[cfg(py_sys_config="Py_TRACE_REFS")] fn PyModule_FromDefAndSpec2TraceRefs(def: *mut PyModuleDef, - spec: *mut PyObject, - module_api_version: c_int) - -> *mut PyObject; + spec: *mut PyObject, + module_api_version: c_int) -> *mut PyObject; } #[cfg(py_sys_config="Py_TRACE_REFS")] @@ -82,8 +71,7 @@ pub unsafe fn PyModule_Create2(module: *mut PyModuleDef, #[inline] pub unsafe fn PyModule_FromDefAndSpec2(def: *mut PyModuleDef, spec: *mut PyObject, - module_api_version: c_int) - -> *mut PyObject { + module_api_version: c_int) -> *mut PyObject { PyModule_FromDefAndSpec2TraceRefs(def, spec, module_api_version) } diff --git a/src/ffi/object.rs b/src/ffi/object.rs index b6635776..f5fbd48e 100644 --- a/src/ffi/object.rs +++ b/src/ffi/object.rs @@ -53,8 +53,7 @@ pub type unaryfunc = unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; pub type binaryfunc = - unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject) - -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; pub type ternaryfunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject, @@ -67,8 +66,7 @@ pub type lenfunc = unsafe extern "C" fn(arg1: *mut PyObject) -> Py_ssize_t; pub type ssizeargfunc = - unsafe extern "C" fn(arg1: *mut PyObject, arg2: Py_ssize_t) - -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; pub type ssizessizeargfunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: Py_ssize_t, @@ -80,8 +78,7 @@ pub type ssizeobjargproc = pub type ssizessizeobjargproc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: Py_ssize_t, - arg3: Py_ssize_t, arg4: *mut PyObject) - -> c_int; + arg3: Py_ssize_t, arg4: *mut PyObject) -> c_int; pub type objobjargproc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject, @@ -174,11 +171,9 @@ pub type destructor = pub type printfunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut ::libc::FILE, arg3: c_int) -> c_int; pub type getattrfunc = - unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut c_char) - -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut c_char) -> *mut PyObject; pub type getattrofunc = - unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject) - -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; pub type setattrfunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut c_char, arg3: *mut PyObject) -> c_int; @@ -186,20 +181,15 @@ pub type setattrofunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> c_int; pub type reprfunc = - unsafe extern "C" fn(arg1: *mut PyObject) - -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; pub type hashfunc = - unsafe extern "C" fn(arg1: *mut PyObject) - -> Py_hash_t; + unsafe extern "C" fn(arg1: *mut PyObject) -> Py_hash_t; pub type richcmpfunc = - unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject, - arg3: c_int) -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int) -> *mut PyObject; pub type getiterfunc = - unsafe extern "C" fn(arg1: *mut PyObject) - -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; pub type iternextfunc = - unsafe extern "C" fn(arg1: *mut PyObject) - -> *mut PyObject; + unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; pub type descrgetfunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> *mut PyObject; @@ -211,8 +201,7 @@ pub type initproc = arg3: *mut PyObject) -> c_int; pub type newfunc = unsafe extern "C" fn(arg1: *mut PyTypeObject, - arg2: *mut PyObject, arg3: *mut PyObject) - -> *mut PyObject; + arg2: *mut PyObject, arg3: *mut PyObject) -> *mut PyObject; pub type allocfunc = unsafe extern "C" fn(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyObject; @@ -644,8 +633,7 @@ pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int { #[cfg_attr(windows, link(name="pythonXY"))] extern "C" { pub fn PyType_Ready(t: *mut PyTypeObject) -> c_int; - pub fn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) - -> *mut PyObject; + pub fn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) -> *mut PyObject; pub fn PyType_GenericNew(t: *mut PyTypeObject, args: *mut PyObject, kwds: *mut PyObject) -> *mut PyObject; pub fn PyType_ClearCache() -> c_uint; @@ -662,32 +650,26 @@ pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int { pub fn PyObject_RichCompareBool(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int) -> c_int; pub fn PyObject_GetAttrString(arg1: *mut PyObject, - arg2: *const c_char) - -> *mut PyObject; + arg2: *const c_char) -> *mut PyObject; pub fn PyObject_SetAttrString(arg1: *mut PyObject, arg2: *const c_char, arg3: *mut PyObject) -> c_int; - pub fn PyObject_HasAttrString(arg1: *mut PyObject, - arg2: *const c_char) - -> c_int; - pub fn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) - -> *mut PyObject; + pub fn PyObject_HasAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int; + pub fn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; pub fn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> c_int; - pub fn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) - -> c_int; + pub fn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; pub fn PyObject_SelfIter(arg1: *mut PyObject) -> *mut PyObject; #[cfg(not(Py_LIMITED_API))] pub fn _PyObject_NextNotImplemented(arg1: *mut PyObject) -> *mut PyObject; pub fn PyObject_GenericGetAttr(arg1: *mut PyObject, arg2: *mut PyObject) - -> *mut PyObject; + -> *mut PyObject; pub fn PyObject_GenericSetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> c_int; pub fn PyObject_GenericSetDict(arg1: *mut PyObject, arg2: *mut PyObject, - arg3: *mut c_void) - -> c_int; + arg3: *mut c_void) -> c_int; pub fn PyObject_Hash(arg1: *mut PyObject) -> Py_hash_t; pub fn PyObject_HashNotImplemented(arg1: *mut PyObject) -> Py_hash_t; pub fn PyObject_IsTrue(arg1: *mut PyObject) -> c_int; @@ -840,7 +822,7 @@ pub const Py_NE : c_int = 3; pub const Py_GT : c_int = 4; pub const Py_GE : c_int = 5; - +#[inline] pub fn PyObject_Check(_arg1: *mut PyObject) -> c_int { 1 } diff --git a/src/ffi/pyhash.rs b/src/ffi/pyhash.rs index b137aa47..2f602860 100644 --- a/src/ffi/pyhash.rs +++ b/src/ffi/pyhash.rs @@ -18,5 +18,4 @@ impl Default for PyHash_FuncDef { #[cfg_attr(windows, link(name="pythonXY"))] extern "C" { pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef; -} - +} \ No newline at end of file diff --git a/src/ffi/tupleobject.rs b/src/ffi/tupleobject.rs index 253cacf6..d5395533 100644 --- a/src/ffi/tupleobject.rs +++ b/src/ffi/tupleobject.rs @@ -27,8 +27,7 @@ pub unsafe fn PyTuple_CheckExact(op : *mut PyObject) -> c_int { #[cfg_attr(windows, link(name="pythonXY"))] extern "C" { pub fn PyTuple_New(size: Py_ssize_t) -> *mut PyObject; pub fn PyTuple_Size(arg1: *mut PyObject) -> Py_ssize_t; - pub fn PyTuple_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) - -> *mut PyObject; + pub fn PyTuple_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; pub fn PyTuple_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject) -> c_int; pub fn PyTuple_GetSlice(arg1: *mut PyObject, arg2: Py_ssize_t, @@ -56,4 +55,3 @@ pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { *(*(op as *mut PyTupleObject)).ob_item.as_mut_ptr().offset(i as isize) = v; } - diff --git a/src/ffi2/boolobject.rs b/src/ffi2/boolobject.rs new file mode 100644 index 00000000..1ea79af4 --- /dev/null +++ b/src/ffi2/boolobject.rs @@ -0,0 +1,28 @@ +use std::os::raw::{c_int, c_long}; +use ffi2::object::*; +use ffi2::intobject::PyIntObject; + +pub type PyBoolObject = PyIntObject; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyBool_Type: PyTypeObject; + static mut _Py_ZeroStruct: PyIntObject; + static mut _Py_TrueStruct: PyIntObject; + pub fn PyBool_FromLong(arg1: c_long) -> *mut PyObject; +} + +#[inline(always)] +pub unsafe fn PyBool_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyBool_Type; + (Py_TYPE(op) == u) as c_int +} + +#[inline(always)] +pub unsafe fn Py_False() -> *mut PyObject { + &mut _Py_ZeroStruct as *mut PyBoolObject as *mut PyObject +} + +#[inline(always)] +pub unsafe fn Py_True() -> *mut PyObject { + &mut _Py_TrueStruct as *mut PyBoolObject as *mut PyObject +} diff --git a/src/ffi2/bufferobject.rs b/src/ffi2/bufferobject.rs new file mode 100644 index 00000000..868ef0d3 --- /dev/null +++ b/src/ffi2/bufferobject.rs @@ -0,0 +1,28 @@ +use std::os::raw::{c_void, c_int}; +use ffi2::object::*; +use ffi2::pyport::Py_ssize_t; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyBuffer_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyBuffer_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyBuffer_Type; + (Py_TYPE(op) == u) as c_int +} + +pub const Py_END_OF_BUFFER: Py_ssize_t = -1; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyBuffer_FromObject(base: *mut PyObject, offset: Py_ssize_t, + size: Py_ssize_t) -> *mut PyObject; + pub fn PyBuffer_FromReadWriteObject(base: *mut PyObject, + offset: Py_ssize_t, size: Py_ssize_t) + -> *mut PyObject; + pub fn PyBuffer_FromMemory(ptr: *mut c_void, size: Py_ssize_t) + -> *mut PyObject; + pub fn PyBuffer_FromReadWriteMemory(ptr: *mut c_void, + size: Py_ssize_t) -> *mut PyObject; + pub fn PyBuffer_New(size: Py_ssize_t) -> *mut PyObject; +} diff --git a/src/ffi2/bytearrayobject.rs b/src/ffi2/bytearrayobject.rs new file mode 100644 index 00000000..a5c52901 --- /dev/null +++ b/src/ffi2/bytearrayobject.rs @@ -0,0 +1,58 @@ +use std::os::raw::{c_char, c_int}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +/*#[repr(C)] +#[deriving(Copy)] +struct PyByteArrayObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_size: Py_ssize_t, + pub ob_exports: c_int, + pub ob_alloc: Py_ssize_t, + pub ob_bytes: *mut c_char, +}*/ + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyByteArray_Type: PyTypeObject; + pub static mut PyByteArrayIter_Type: PyTypeObject; +} + +pub unsafe fn PyByteArray_Check(op : *mut PyObject) -> c_int { + PyObject_TypeCheck(op, &mut PyByteArray_Type) +} + +pub unsafe fn PyByteArray_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyByteArray_Type; + (Py_TYPE(op) == u) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyByteArray_FromObject(o: *mut PyObject) -> *mut PyObject; + pub fn PyByteArray_Concat(a: *mut PyObject, b: *mut PyObject) + -> *mut PyObject; + pub fn PyByteArray_FromStringAndSize(string: *const c_char, + len: Py_ssize_t) -> *mut PyObject; + pub fn PyByteArray_Size(bytearray: *mut PyObject) -> Py_ssize_t; + pub fn PyByteArray_AsString(bytearray: *mut PyObject) -> *mut c_char; + pub fn PyByteArray_Resize(bytearray: *mut PyObject, len: Py_ssize_t) + -> c_int; +} + +#[inline(always)] +pub unsafe fn PyByteArray_AS_STRING(o: *mut PyObject) -> *mut c_char { + PyByteArray_AsString(o) + // #define PyByteArray_AS_STRING(self) \ + // (assert(PyByteArray_Check(self)), \ + // Py_SIZE(self) ? ((PyByteArrayObject *)(self))->ob_bytes : _PyByteArray_empty_string) +} + +#[inline(always)] +pub unsafe fn PyByteArray_GET_SIZE(o: *mut PyObject) -> Py_ssize_t { + // #define PyByteArray_GET_SIZE(self) (assert(PyByteArray_Check(self)),Py_SIZE(self)) + PyByteArray_Size(o) +} diff --git a/src/ffi2/bytesobject.rs b/src/ffi2/bytesobject.rs new file mode 100644 index 00000000..51d49881 --- /dev/null +++ b/src/ffi2/bytesobject.rs @@ -0,0 +1,16 @@ +pub use ffi2::stringobject::PyStringObject as PyBytesObject; +pub use ffi2::stringobject::PyString_Type as PyBytes_Type; +pub use ffi2::stringobject::PyString_Check as PyBytes_Check; +pub use ffi2::stringobject::PyString_CheckExact as PyBytes_CheckExact; +pub use ffi2::stringobject::PyString_AS_STRING as PyBytes_AS_STRING; +pub use ffi2::stringobject::PyString_GET_SIZE as PyBytes_GET_SIZE; +pub use ffi2::object::Py_TPFLAGS_STRING_SUBCLASS as Py_TPFLAGS_BYTES_SUBCLASS; +pub use ffi2::stringobject::PyString_FromStringAndSize as PyBytes_FromStringAndSize; +pub use ffi2::stringobject::PyString_FromString as PyBytes_FromString; +pub use ffi2::stringobject::PyString_FromFormat as PyBytes_FromFormat; +pub use ffi2::stringobject::PyString_Size as PyBytes_Size; +pub use ffi2::stringobject::PyString_AsString as PyBytes_AsString; +pub use ffi2::stringobject::PyString_Concat as PyBytes_Concat; +pub use ffi2::stringobject::PyString_ConcatAndDel as PyBytes_ConcatAndDel; +pub use ffi2::stringobject::PyString_Format as PyBytes_Format; +pub use ffi2::stringobject::PyString_AsStringAndSize as PyBytes_AsStringAndSize; diff --git a/src/ffi2/cellobject.rs b/src/ffi2/cellobject.rs new file mode 100644 index 00000000..3edb4e57 --- /dev/null +++ b/src/ffi2/cellobject.rs @@ -0,0 +1,40 @@ +use std::os::raw::c_int; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +struct PyCellObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_ref: *mut PyObject +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyCell_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyCell_Check(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyCell_Type) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyCell_New(obj: *mut PyObject) -> *mut PyObject; + pub fn PyCell_Get(op: *mut PyObject) -> *mut PyObject; + pub fn PyCell_Set(op: *mut PyObject, obj: *mut PyObject) -> c_int; +} + +#[inline(always)] +pub unsafe fn PyCell_GET(op: *mut PyObject) -> *mut PyObject { + (*(op as *mut PyCellObject)).ob_ref +} + +#[inline(always)] +pub unsafe fn PyCell_SET(op: *mut PyObject, obj: *mut PyObject) { + (*(op as *mut PyCellObject)).ob_ref = obj; +} diff --git a/src/ffi2/ceval.rs b/src/ffi2/ceval.rs new file mode 100644 index 00000000..316ca0a1 --- /dev/null +++ b/src/ffi2/ceval.rs @@ -0,0 +1,55 @@ +use std::os::raw::{c_void, c_char, c_int}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::PyObject; +use ffi2::frameobject::PyFrameObject; +use ffi2::pystate::{PyThreadState, Py_tracefunc}; +use ffi2::pythonrun::PyCompilerFlags; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyEval_CallObjectWithKeywords(callable: *mut PyObject, + args: *mut PyObject, + kwds: *mut PyObject) -> *mut PyObject; + pub fn PyEval_CallFunction(obj: *mut PyObject, + format: *const c_char, ...) -> *mut PyObject; + pub fn PyEval_CallMethod(obj: *mut PyObject, + methodname: *const c_char, + format: *const c_char, ...) -> *mut PyObject; + pub fn PyEval_SetProfile(func: Option, obj: *mut PyObject); + pub fn PyEval_SetTrace(func: Option, obj: *mut PyObject); + pub fn PyEval_GetBuiltins() -> *mut PyObject; + pub fn PyEval_GetGlobals() -> *mut PyObject; + pub fn PyEval_GetLocals() -> *mut PyObject; + pub fn PyEval_GetFrame() -> *mut PyFrameObject; + pub fn PyEval_GetRestricted() -> c_int; + pub fn PyEval_MergeCompilerFlags(cf: *mut PyCompilerFlags) -> c_int; + pub fn Py_FlushLine() -> c_int; + pub fn Py_AddPendingCall(func: Option c_int>, + arg: *mut c_void) -> c_int; + pub fn Py_MakePendingCalls() -> c_int; + pub fn Py_SetRecursionLimit(arg1: c_int); + pub fn Py_GetRecursionLimit() -> c_int; + fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int; + + pub fn PyEval_GetFuncName(arg1: *mut PyObject) -> *const c_char; + pub fn PyEval_GetFuncDesc(arg1: *mut PyObject) -> *const c_char; + pub fn PyEval_GetCallStats(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyEval_EvalFrame(arg1: *mut PyFrameObject) -> *mut PyObject; + pub fn PyEval_EvalFrameEx(f: *mut PyFrameObject, exc: c_int) -> *mut PyObject; + pub fn PyEval_SaveThread() -> *mut PyThreadState; + pub fn PyEval_RestoreThread(arg1: *mut PyThreadState); + + fn _PyEval_SliceIndex(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int; +} + +#[cfg(py_sys_config="WITH_THREAD")] +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyEval_ThreadsInitialized() -> c_int; + pub fn PyEval_InitThreads(); + pub fn PyEval_AcquireLock(); + pub fn PyEval_ReleaseLock(); + pub fn PyEval_AcquireThread(tstate: *mut PyThreadState); + pub fn PyEval_ReleaseThread(tstate: *mut PyThreadState); + pub fn PyEval_ReInitThreads(); +} + diff --git a/src/ffi2/classobject.rs b/src/ffi2/classobject.rs new file mode 100644 index 00000000..a11e49d1 --- /dev/null +++ b/src/ffi2/classobject.rs @@ -0,0 +1,109 @@ +use std::os::raw::c_int; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyClassObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub cl_bases: *mut PyObject, + pub cl_dict: *mut PyObject, + pub cl_name: *mut PyObject, + pub cl_getattr: *mut PyObject, + pub cl_setattr: *mut PyObject, + pub cl_delattr: *mut PyObject, + pub cl_weakreflist: *mut PyObject, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyInstanceObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub in_class: *mut PyClassObject, + pub in_dict: *mut PyObject, + pub in_weakreflist: *mut PyObject, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyMethodObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub im_func: *mut PyObject, + pub im_self: *mut PyObject, + pub im_class: *mut PyObject, + pub im_weakreflist: *mut PyObject, +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyClass_Type: PyTypeObject; + pub static mut PyInstance_Type: PyTypeObject; + pub static mut PyMethod_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyClass_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyClass_Type; + (Py_TYPE(op) == u) as c_int +} + +#[inline(always)] +pub unsafe fn PyInstance_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyInstance_Type; + (Py_TYPE(op) == u) as c_int +} + +#[inline(always)] +pub unsafe fn PyMethod_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyMethod_Type; + (Py_TYPE(op) == u) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyClass_New(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> *mut PyObject; + pub fn PyInstance_New(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> *mut PyObject; + pub fn PyInstance_NewRaw(arg1: *mut PyObject, arg2: *mut PyObject) + -> *mut PyObject; + pub fn PyMethod_New(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> *mut PyObject; + pub fn PyMethod_Function(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyMethod_Self(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyMethod_Class(arg1: *mut PyObject) -> *mut PyObject; + fn _PyInstance_Lookup(pinst: *mut PyObject, name: *mut PyObject) + -> *mut PyObject; + pub fn PyClass_IsSubclass(arg1: *mut PyObject, arg2: *mut PyObject) + -> c_int; + pub fn PyMethod_ClearFreeList() -> c_int; +} + +#[inline(always)] +pub unsafe fn PyMethod_GET_FUNCTION(meth : *mut PyObject) -> *mut PyObject { + (*(meth as *mut PyMethodObject)).im_func +} + +#[inline(always)] +pub unsafe fn PyMethod_GET_SELF(meth : *mut PyObject) -> *mut PyObject { + (*(meth as *mut PyMethodObject)).im_self +} + +#[inline(always)] +pub unsafe fn PyMethod_GET_CLASS(meth : *mut PyObject) -> *mut PyObject { + (*(meth as *mut PyMethodObject)).im_class +} + diff --git a/src/ffi2/cobject.rs b/src/ffi2/cobject.rs new file mode 100644 index 00000000..b655ae39 --- /dev/null +++ b/src/ffi2/cobject.rs @@ -0,0 +1,27 @@ +use std::os::raw::{c_void, c_char, c_int}; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyCObject_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyCObject_Check(op : *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyCObject_Type) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyCObject_FromVoidPtr(cobj: *mut c_void, + destruct: Option) + -> *mut PyObject; + pub fn PyCObject_FromVoidPtrAndDesc( + cobj: *mut c_void, + desc: *mut c_void, + destruct: Option) + -> *mut PyObject; + pub fn PyCObject_AsVoidPtr(arg1: *mut PyObject) -> *mut c_void; + pub fn PyCObject_GetDesc(arg1: *mut PyObject) -> *mut c_void; + pub fn PyCObject_Import(module_name: *mut c_char, + cobject_name: *mut c_char) -> *mut c_void; + pub fn PyCObject_SetVoidPtr(_self: *mut PyObject, cobj: *mut c_void) -> c_int; +} diff --git a/src/ffi2/code.rs b/src/ffi2/code.rs new file mode 100644 index 00000000..5301a1dc --- /dev/null +++ b/src/ffi2/code.rs @@ -0,0 +1,87 @@ +use std::os::raw::{c_char, c_int, c_void}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyCodeObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub co_argcount: c_int, + pub co_nlocals: c_int, + pub co_stacksize: c_int, + pub co_flags: c_int, + pub co_code: *mut PyObject, + pub co_consts: *mut PyObject, + pub co_names: *mut PyObject, + pub co_varnames: *mut PyObject, + pub co_freevars: *mut PyObject, + pub co_cellvars: *mut PyObject, + pub co_filename: *mut PyObject, + pub co_name: *mut PyObject, + pub co_firstlineno: c_int, + pub co_lnotab: *mut PyObject, + pub co_zombieframe: *mut c_void, + pub co_weakreflist: *mut PyObject, +} + +/* Masks for co_flags */ +pub const CO_OPTIMIZED : c_int = 0x0001; +pub const CO_NEWLOCALS : c_int = 0x0002; +pub const CO_VARARGS : c_int = 0x0004; +pub const CO_VARKEYWORDS : c_int = 0x0008; +pub const CO_NESTED : c_int = 0x0010; +pub const CO_GENERATOR : c_int = 0x0020; +/* The CO_NOFREE flag is set if there are no free or cell variables. + This information is redundant, but it allows a single flag test + to determine whether there is any extra work to be done when the + call frame it setup. +*/ +pub const CO_NOFREE : c_int = 0x0040; + +pub const CO_FUTURE_DIVISION : c_int = 0x2000; +pub const CO_FUTURE_ABSOLUTE_IMPORT : c_int = 0x4000; /* do absolute imports by default */ +pub const CO_FUTURE_WITH_STATEMENT : c_int = 0x8000; +pub const CO_FUTURE_PRINT_FUNCTION : c_int = 0x10000; +pub const CO_FUTURE_UNICODE_LITERALS : c_int = 0x20000; + +pub const CO_MAXBLOCKS : usize = 20; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyCode_Type: PyTypeObject; + + pub fn PyCode_New(arg1: c_int, arg2: c_int, + arg3: c_int, arg4: c_int, + arg5: *mut PyObject, arg6: *mut PyObject, + arg7: *mut PyObject, arg8: *mut PyObject, + arg9: *mut PyObject, arg10: *mut PyObject, + arg11: *mut PyObject, arg12: *mut PyObject, + arg13: c_int, arg14: *mut PyObject) + -> *mut PyCodeObject; + pub fn PyCode_NewEmpty(filename: *const c_char, + funcname: *const c_char, + firstlineno: c_int) -> *mut PyCodeObject; + pub fn PyCode_Addr2Line(arg1: *mut PyCodeObject, arg2: c_int) + -> c_int; + //fn _PyCode_CheckLineNumber(co: *mut PyCodeObject, + // lasti: c_int, + // bounds: *mut PyAddrPair) -> c_int; + pub fn PyCode_Optimize(code: *mut PyObject, consts: *mut PyObject, + names: *mut PyObject, lineno_obj: *mut PyObject) + -> *mut PyObject; +} + +#[inline(always)] +pub unsafe fn PyCode_Check(op : *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyCode_Type) as c_int +} + +#[inline] +pub unsafe fn PyCode_GetNumFree(op : *mut PyCodeObject) -> Py_ssize_t { + ::ffi2::tupleobject::PyTuple_GET_SIZE((*op).co_freevars) +} + diff --git a/src/ffi2/compile.rs b/src/ffi2/compile.rs new file mode 100644 index 00000000..a136e8f5 --- /dev/null +++ b/src/ffi2/compile.rs @@ -0,0 +1,29 @@ +use std::os::raw::{c_char, c_int}; +use ffi2::pythonrun::*; +use ffi2::code::*; +use ffi2::pyarena::PyArena; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyFutureFeatures { + pub ff_features: c_int, + pub ff_lineno: c_int, +} + +pub const FUTURE_NESTED_SCOPES : &'static str = "nested_scopes"; +pub const FUTURE_GENERATORS : &'static str = "generators"; +pub const FUTURE_DIVISION : &'static str = "division"; +pub const FUTURE_ABSOLUTE_IMPORT : &'static str = "absolute_import"; +pub const FUTURE_WITH_STATEMENT : &'static str = "with_statement"; +pub const FUTURE_PRINT_FUNCTION : &'static str = "print_function"; +pub const FUTURE_UNICODE_LITERALS : &'static str = "unicode_literals"; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyNode_Compile(arg1: *mut Struct__node, + arg2: *const c_char) -> *mut PyCodeObject; + pub fn PyAST_Compile(arg1: *mut Struct__mod, arg2: *const c_char, + arg3: *mut PyCompilerFlags, arg4: *mut PyArena) + -> *mut PyCodeObject; + pub fn PyFuture_FromAST(arg1: *mut Struct__mod, + arg2: *const c_char) -> *mut PyFutureFeatures; +} diff --git a/src/ffi2/complexobject.rs b/src/ffi2/complexobject.rs new file mode 100644 index 00000000..f0d1b9d2 --- /dev/null +++ b/src/ffi2/complexobject.rs @@ -0,0 +1,63 @@ +use std::os::raw::{c_double, c_int}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Py_complex { + pub real: c_double, + pub imag: c_double +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn _Py_c_sum(left: Py_complex, right: Py_complex) -> Py_complex; + pub fn _Py_c_diff(left: Py_complex, right: Py_complex) -> Py_complex; + pub fn _Py_c_neg(complex: Py_complex) -> Py_complex; + pub fn _Py_c_prod(left: Py_complex, right: Py_complex) -> Py_complex; + pub fn _Py_c_quot(dividend: Py_complex, divisor: Py_complex) -> Py_complex; + pub fn _Py_c_pow(num: Py_complex, exp: Py_complex) -> Py_complex; + pub fn _Py_c_abs(arg: Py_complex) -> c_double; +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyComplexObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub cval: Py_complex +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyComplex_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyComplex_Check(op : *mut PyObject) -> c_int { + PyObject_TypeCheck(op, &mut PyComplex_Type) +} + +#[inline(always)] +pub unsafe fn PyComplex_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyComplex_Type; + (Py_TYPE(op) == u) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyComplex_FromCComplex(v: Py_complex) -> *mut PyObject; + pub fn PyComplex_FromDoubles(real: c_double, + imag: c_double) -> *mut PyObject; + pub fn PyComplex_RealAsDouble(op: *mut PyObject) -> c_double; + pub fn PyComplex_ImagAsDouble(op: *mut PyObject) -> c_double; + pub fn PyComplex_AsCComplex(op: *mut PyObject) -> Py_complex; + + + //fn _PyComplex_FormatAdvanced(obj: *mut PyObject, + // format_spec: *mut c_char, + // format_spec_len: Py_ssize_t) + // -> *mut PyObject; +} + diff --git a/src/ffi2/descrobject.rs b/src/ffi2/descrobject.rs new file mode 100644 index 00000000..6a06c56c --- /dev/null +++ b/src/ffi2/descrobject.rs @@ -0,0 +1,97 @@ +use std::ptr; +use std::os::raw::{c_void, c_char, c_int}; +use ffi2::object::{PyObject, PyTypeObject, Py_TYPE}; +use ffi2::structmember::PyMemberDef; +use ffi2::methodobject::PyMethodDef; + +pub type getter = + unsafe extern "C" fn + (slf: *mut PyObject, closure: *mut c_void) -> *mut PyObject; + +pub type setter = + unsafe extern "C" fn (slf: *mut PyObject, value: *mut PyObject, + closure: *mut c_void) -> c_int; + +#[repr(C)] +#[derive(Copy)] +pub struct PyGetSetDef { + pub name: *mut c_char, + pub get: Option, + pub set: Option, + pub doc: *mut c_char, + pub closure: *mut c_void, +} + +pub const PyGetSetDef_INIT : PyGetSetDef = PyGetSetDef { + name: ptr::null_mut(), + get: None, + set: None, + doc: ptr::null_mut(), + closure: ptr::null_mut(), +}; + +impl Clone for PyGetSetDef { + #[inline] fn clone(&self) -> PyGetSetDef { *self } +} + +pub type wrapperfunc = + unsafe extern "C" fn(slf: *mut PyObject, args: *mut PyObject, + wrapped: *mut c_void) -> *mut PyObject; + +pub type wrapperfunc_kwds = + unsafe extern "C" fn(slf: *mut PyObject, args: *mut PyObject, + wrapped: *mut c_void, kwds: *mut PyObject) -> *mut PyObject; + +#[repr(C)] +#[derive(Copy)] +pub struct wrapperbase { + pub name: *mut c_char, + pub offset: c_int, + pub function: *mut c_void, + pub wrapper: Option, + pub doc: *mut c_char, + pub flags: c_int, + pub name_strobj: *mut PyObject +} + +impl Clone for wrapperbase { + #[inline] fn clone(&self) -> wrapperbase { *self } +} + +pub const PyWrapperFlag_KEYWORDS : c_int = 1; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyWrapperDescr_Type: PyTypeObject; + pub static mut PyDictProxy_Type: PyTypeObject; + pub static mut PyGetSetDescr_Type: PyTypeObject; + pub static mut PyMemberDescr_Type: PyTypeObject; + pub static mut PyProperty_Type: PyTypeObject; + + pub fn PyDescr_NewMethod(arg1: *mut PyTypeObject, arg2: *mut PyMethodDef) + -> *mut PyObject; + pub fn PyDescr_NewClassMethod(arg1: *mut PyTypeObject, + arg2: *mut PyMethodDef) -> *mut PyObject; + pub fn PyDescr_NewMember(arg1: *mut PyTypeObject, + arg2: *mut PyMemberDef) -> *mut PyObject; + pub fn PyDescr_NewGetSet(arg1: *mut PyTypeObject, + arg2: *mut PyGetSetDef) -> *mut PyObject; + pub fn PyDescr_NewWrapper(arg1: *mut PyTypeObject, + arg2: *mut wrapperbase, + arg3: *mut c_void) -> *mut PyObject; +} + +#[inline(always)] +pub unsafe fn PyDescr_IsData(d: *mut PyObject) -> c_int { + (*Py_TYPE(d)).tp_descr_set.is_some() as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + //pub fn PyDictProxy_New(arg1: *mut PyObject) -> *mut PyObject; + // PyDictProxy_New is also defined in dictobject.h + pub fn PyWrapper_New(arg1: *mut PyObject, arg2: *mut PyObject) + -> *mut PyObject; +} + + + + diff --git a/src/ffi2/dictobject.rs b/src/ffi2/dictobject.rs new file mode 100644 index 00000000..57263ac2 --- /dev/null +++ b/src/ffi2/dictobject.rs @@ -0,0 +1,71 @@ +use std::os::raw::{c_char, c_int}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +//pub enum PyDictObject { /* representation hidden */ } + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyDict_Type: PyTypeObject; + pub static mut PyDictIterKey_Type: PyTypeObject; + pub static mut PyDictIterValue_Type: PyTypeObject; + pub static mut PyDictIterItem_Type: PyTypeObject; + pub static mut PyDictKeys_Type: PyTypeObject; + pub static mut PyDictItems_Type: PyTypeObject; + pub static mut PyDictValues_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyDict_Check(op : *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyDict_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyDict_Type; + (Py_TYPE(op) == u) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyDict_New() -> *mut PyObject; + pub fn PyDictProxy_New(dict: *mut PyObject) -> *mut PyObject; + pub fn PyDict_Clear(mp: *mut PyObject); + pub fn PyDict_Contains(mp: *mut PyObject, key: *mut PyObject) + -> c_int; + pub fn PyDict_Copy(mp: *mut PyObject) -> *mut PyObject; + + pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) + -> *mut PyObject; + pub fn PyDict_SetItem(mp: *mut PyObject, key: *mut PyObject, + item: *mut PyObject) -> c_int; + pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) + -> c_int; + pub fn PyDict_GetItemString(dp: *mut PyObject, key: *const c_char) + -> *mut PyObject; + pub fn PyDict_SetItemString(dp: *mut PyObject, key: *const c_char, + item: *mut PyObject) -> c_int; + pub fn PyDict_DelItemString(dp: *mut PyObject, key: *const c_char) + -> c_int; + + pub fn PyDict_Keys(mp: *mut PyObject) -> *mut PyObject; + pub fn PyDict_Values(mp: *mut PyObject) -> *mut PyObject; + pub fn PyDict_Items(mp: *mut PyObject) -> *mut PyObject; + pub fn PyDict_Size(mp: *mut PyObject) -> Py_ssize_t; + pub fn PyDict_Next(mp: *mut PyObject, pos: *mut Py_ssize_t, + key: *mut *mut PyObject, value: *mut *mut PyObject) + -> c_int; + /*pub fn _PyDict_Next(mp: *mut PyObject, pos: *mut Py_ssize_t, + key: *mut *mut PyObject, value: *mut *mut PyObject, + hash: *mut c_long) -> c_int; + pub fn _PyDict_Contains(mp: *mut PyObject, key: *mut PyObject, + hash: c_long) -> c_int; + pub fn _PyDict_NewPresized(minused: Py_ssize_t) -> *mut PyObject; + pub fn _PyDict_MaybeUntrack(mp: *mut PyObject);*/ + pub fn PyDict_Update(mp: *mut PyObject, other: *mut PyObject) + -> c_int; + pub fn PyDict_Merge(mp: *mut PyObject, other: *mut PyObject, + _override: c_int) -> c_int; + pub fn PyDict_MergeFromSeq2(d: *mut PyObject, seq2: *mut PyObject, + _override: c_int) -> c_int; + +} + diff --git a/src/ffi2/enumobject.rs b/src/ffi2/enumobject.rs new file mode 100644 index 00000000..50424901 --- /dev/null +++ b/src/ffi2/enumobject.rs @@ -0,0 +1,7 @@ +use ffi2::object::PyTypeObject; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyEnum_Type: PyTypeObject; + pub static mut PyReversed_Type: PyTypeObject; +} + diff --git a/src/ffi2/eval.rs b/src/ffi2/eval.rs new file mode 100644 index 00000000..4a2660f7 --- /dev/null +++ b/src/ffi2/eval.rs @@ -0,0 +1,16 @@ +use std::os::raw::c_int; +use ffi2::object::PyObject; +use ffi2::code::PyCodeObject; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyEval_EvalCode(arg1: *mut PyCodeObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> *mut PyObject; + pub fn PyEval_EvalCodeEx(co: *mut PyCodeObject, globals: *mut PyObject, + locals: *mut PyObject, args: *mut *mut PyObject, + argc: c_int, kwds: *mut *mut PyObject, + kwdc: c_int, defs: *mut *mut PyObject, + defc: c_int, closure: *mut PyObject) + -> *mut PyObject; + fn _PyEval_CallTracing(func: *mut PyObject, args: *mut PyObject) + -> *mut PyObject; +} diff --git a/src/ffi2/fileobject.rs b/src/ffi2/fileobject.rs new file mode 100644 index 00000000..6838ca3e --- /dev/null +++ b/src/ffi2/fileobject.rs @@ -0,0 +1,59 @@ +use libc::{size_t, FILE}; +use std::os::raw::{c_char, c_int}; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyFile_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyFile_Check(op : *mut PyObject) -> c_int { + PyObject_TypeCheck(op, &mut PyFile_Type) +} + +#[inline(always)] +pub unsafe fn PyFile_CheckExact(op : *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyFile_Type) as c_int +} + + +pub const PY_STDIOTEXTMODE : &'static str = "b"; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyFile_FromString(arg1: *mut c_char, + arg2: *mut c_char) -> *mut PyObject; + pub fn PyFile_SetBufSize(arg1: *mut PyObject, arg2: c_int); + pub fn PyFile_SetEncoding(arg1: *mut PyObject, + arg2: *const c_char) -> c_int; + pub fn PyFile_SetEncodingAndErrors(arg1: *mut PyObject, + arg2: *const c_char, + errors: *mut c_char) + -> c_int; + pub fn PyFile_FromFile(arg1: *mut FILE, arg2: *mut c_char, + arg3: *mut c_char, + arg4: Option c_int>) + -> *mut PyObject; + pub fn PyFile_AsFile(arg1: *mut PyObject) -> *mut FILE; + //pub fn PyFile_IncUseCount(arg1: *mut PyFileObject); + //pub fn PyFile_DecUseCount(arg1: *mut PyFileObject); + pub fn PyFile_Name(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyFile_GetLine(arg1: *mut PyObject, arg2: c_int) + -> *mut PyObject; + pub fn PyFile_WriteObject(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: c_int) -> c_int; + pub fn PyFile_SoftSpace(arg1: *mut PyObject, arg2: c_int) + -> c_int; + pub fn PyFile_WriteString(arg1: *const c_char, + arg2: *mut PyObject) -> c_int; + pub fn PyObject_AsFileDescriptor(arg1: *mut PyObject) -> c_int; + pub fn Py_UniversalNewlineFgets(arg1: *mut c_char, + arg2: c_int, arg3: *mut FILE, + arg4: *mut PyObject) + -> *mut c_char; + pub fn Py_UniversalNewlineFread(arg1: *mut c_char, arg2: size_t, + arg3: *mut FILE, arg4: *mut PyObject) + -> size_t; + + pub static mut Py_FileSystemDefaultEncoding: *const c_char; +} + diff --git a/src/ffi2/floatobject.rs b/src/ffi2/floatobject.rs new file mode 100644 index 00000000..faa0688b --- /dev/null +++ b/src/ffi2/floatobject.rs @@ -0,0 +1,50 @@ +use std::os::raw::{c_char, c_int, c_double}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +struct PyFloatObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_fval: c_double +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyFloat_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyFloat_Check(op : *mut PyObject) -> c_int { + PyObject_TypeCheck(op, &mut PyFloat_Type) +} + +#[inline(always)] +pub unsafe fn PyFloat_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyFloat_Type; + (Py_TYPE(op) == u) as c_int +} + +pub const PyFloat_STR_PRECISION : c_int = 12; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyFloat_FromString(str: *mut PyObject, + pend: *mut *mut c_char) + -> *mut PyObject; + pub fn PyFloat_FromDouble(v: c_double) -> *mut PyObject; + pub fn PyFloat_AsDouble(pyfloat: *mut PyObject) -> c_double; + pub fn PyFloat_GetInfo() -> *mut PyObject; + + pub fn PyFloat_GetMax() -> c_double; + pub fn PyFloat_GetMin() -> c_double; + pub fn PyFloat_ClearFreeList() -> c_int; +} + +pub unsafe fn PyFloat_AS_DOUBLE(pyfloat: *mut PyObject) -> c_double { + (*(pyfloat as *mut PyFloatObject)).ob_fval +} + diff --git a/src/ffi2/frameobject.rs b/src/ffi2/frameobject.rs new file mode 100644 index 00000000..004b5440 --- /dev/null +++ b/src/ffi2/frameobject.rs @@ -0,0 +1,82 @@ +use std::os::raw::c_int; +use ffi2::object::*; +use ffi2::pyport::Py_ssize_t; +use ffi2::code::{PyCodeObject, CO_MAXBLOCKS}; +use ffi2::pystate::PyThreadState; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyTryBlock { + pub b_type : c_int, + pub b_handler : c_int, + pub b_level : c_int, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyFrameObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_size: Py_ssize_t, + pub f_back: *mut PyFrameObject, /* previous frame, or NULL */ + pub f_code: *mut PyCodeObject, /* code segment */ + pub f_builtins: *mut PyObject, /* builtin symbol table (PyDictObject) */ + pub f_globals: *mut PyObject, /* global symbol table (PyDictObject) */ + pub f_locals: *mut PyObject, /* local symbol table (any mapping) */ + pub f_valuestack: *mut *mut PyObject, /* points after the last local */ + /* Next free slot in f_valuestack. Frame creation sets to f_valuestack. + Frame evaluation usually NULLs it, but a frame that yields sets it + to the current stack top. */ + pub f_stacktop: *mut *mut PyObject, + pub f_trace: *mut PyObject, /* Trace function */ + + pub f_exc_type: *mut PyObject, + pub f_exc_value: *mut PyObject, + pub f_exc_traceback: *mut PyObject, + + pub f_tstate: *mut PyThreadState, + + pub f_lasti: c_int, /* Last instruction if called */ + /* Call PyFrame_GetLineNumber() instead of reading this field + directly. As of 2.3 f_lineno is only valid when tracing is + active (i.e. when f_trace is set). At other times we use + PyCode_Addr2Line to calculate the line from the current + bytecode index. */ + pub f_lineno: c_int, /* Current line number */ + pub f_iblock: c_int, /* index in f_blockstack */ + pub f_blockstack: [PyTryBlock; CO_MAXBLOCKS], /* for try and loop blocks */ + pub f_localsplus: [*mut PyObject; 1] /* locals+stack, dynamically sized */ +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyFrame_Type: PyTypeObject; +} + +#[inline] +pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int { + ((*op).ob_type == &mut PyFrame_Type) as c_int +} + +//#[inline] +//pub unsafe fn PyFrame_IsRestricted(f: *mut PyFrameObject) -> c_int { +// ((*f).f_builtins != (*(*(*f).f_tstate).interp).builtins) as c_int +//} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyFrame_New(tstate: *mut PyThreadState, code: *mut PyCodeObject, + globals: *mut PyObject, locals: *mut PyObject) -> *mut PyFrameObject; + + pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int) -> (); + pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock; + + pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int) -> (); + pub fn PyFrame_FastToLocals(f: *mut PyFrameObject) -> (); + + pub fn PyFrame_ClearFreeList() -> c_int; + pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int; +} + diff --git a/src/ffi2/funcobject.rs b/src/ffi2/funcobject.rs new file mode 100644 index 00000000..075116a3 --- /dev/null +++ b/src/ffi2/funcobject.rs @@ -0,0 +1,34 @@ +use std::os::raw::c_int; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyFunction_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyFunction_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyFunction_Type; + (Py_TYPE(op) == u) as c_int +} + + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyFunction_New(code: *mut PyObject, globals: *mut PyObject) + -> *mut PyObject; + pub fn PyFunction_GetCode(f: *mut PyObject) -> *mut PyObject; + pub fn PyFunction_GetGlobals(f: *mut PyObject) -> *mut PyObject; + pub fn PyFunction_GetModule(f: *mut PyObject) -> *mut PyObject; + pub fn PyFunction_GetDefaults(f: *mut PyObject) -> *mut PyObject; + pub fn PyFunction_SetDefaults(f: *mut PyObject, defaults: *mut PyObject) + -> c_int; + pub fn PyFunction_GetClosure(f: *mut PyObject) -> *mut PyObject; + pub fn PyFunction_SetClosure(f: *mut PyObject, closure: *mut PyObject) + -> c_int; + + pub static mut PyClassMethod_Type: PyTypeObject; + pub static mut PyStaticMethod_Type: PyTypeObject; + + pub fn PyClassMethod_New(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyStaticMethod_New(arg1: *mut PyObject) -> *mut PyObject; +} + diff --git a/src/ffi2/genobject.rs b/src/ffi2/genobject.rs new file mode 100644 index 00000000..9dd8f2cc --- /dev/null +++ b/src/ffi2/genobject.rs @@ -0,0 +1,39 @@ +use std::os::raw::c_int; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; +use ffi2::frameobject::PyFrameObject; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyGenObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub gi_frame: *mut PyFrameObject, + pub gi_running: c_int, + pub gi_code: *mut PyObject, + pub gi_weakreflist: *mut PyObject +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyGen_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyGen_Check(op: *mut PyObject) -> c_int { + PyObject_TypeCheck(op, &mut PyGen_Type) +} + +#[inline(always)] +pub unsafe fn PyGen_CheckExact(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyGen_Type) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyGen_New(frame: *mut PyFrameObject) -> *mut PyObject; + pub fn PyGen_NeedsFinalizing(op: *mut PyGenObject) -> c_int; +} + diff --git a/src/ffi2/import.rs b/src/ffi2/import.rs new file mode 100644 index 00000000..9b0b7b9e --- /dev/null +++ b/src/ffi2/import.rs @@ -0,0 +1,86 @@ +use std::os::raw::{c_char, c_uchar, c_int, c_long}; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy)] +pub struct PyImport_Struct_inittab { + pub name: *mut c_char, + pub initfunc: Option, +} + +impl Clone for PyImport_Struct_inittab { + #[inline] fn clone(&self) -> PyImport_Struct_inittab { *self } +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyImport_Struct_frozen { + pub name: *mut c_char, + pub code: *mut c_uchar, + pub size: c_int, +} + +#[inline] +pub unsafe fn PyImport_ImportModuleEx(name: *mut c_char, + globals: *mut PyObject, + locals: *mut PyObject, + fromlist: *mut PyObject) -> *mut PyObject { + PyImport_ImportModuleLevel(name, globals, locals, fromlist, -1) +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyImport_ImportModule(name: *const c_char) + -> *mut PyObject; + pub fn PyImport_ImportModuleNoBlock(name: *const c_char) + -> *mut PyObject; + pub fn PyImport_ImportModuleLevel(name: *mut c_char, + globals: *mut PyObject, + locals: *mut PyObject, + fromlist: *mut PyObject, + level: c_int) -> *mut PyObject; + + pub fn PyImport_Import(name: *mut PyObject) -> *mut PyObject; + pub fn PyImport_ReloadModule(m: *mut PyObject) -> *mut PyObject; + pub fn PyImport_AddModule(name: *const c_char) -> *mut PyObject; + pub fn PyImport_ExecCodeModule(name: *mut c_char, + co: *mut PyObject) -> *mut PyObject; + pub fn PyImport_ExecCodeModuleEx(name: *mut c_char, + co: *mut PyObject, + pathname: *mut c_char) + -> *mut PyObject; + pub fn PyImport_GetMagicNumber() -> c_long; + pub fn PyImport_GetImporter(path: *mut PyObject) -> *mut PyObject; + pub fn PyImport_GetModuleDict() -> *mut PyObject; + pub fn PyImport_ImportFrozenModule(name: *mut c_char) + -> c_int; + + pub fn PyImport_AppendInittab(name: *const c_char, + initfunc: + Option) + -> c_int; + pub fn PyImport_ExtendInittab(newtab: *mut PyImport_Struct_inittab) + -> c_int; + + pub static mut PyImport_Inittab: *mut PyImport_Struct_inittab; + pub static mut PyImport_FrozenModules: *mut PyImport_Struct_frozen; + + /*for internal use only: + pub fn PyImport_Cleanup(); + pub fn _PyImport_AcquireLock(); + pub fn _PyImport_ReleaseLock() -> c_int; + pub fn _PyImport_FindModule(arg1: *const c_char, + arg2: *mut PyObject, + arg3: *mut c_char, arg4: size_t, + arg5: *mut *mut FILE, + arg6: *mut *mut PyObject) + -> *mut Struct_filedescr; + pub fn _PyImport_IsScript(arg1: *mut Struct_filedescr) -> c_int; + pub fn _PyImport_ReInitLock(); + pub fn _PyImport_FindExtension(arg1: *mut c_char, + arg2: *mut c_char) + -> *mut PyObject; + pub fn _PyImport_FixupExtension(arg1: *mut c_char, + arg2: *mut c_char) + -> *mut PyObject;*/ +} + diff --git a/src/ffi2/intobject.rs b/src/ffi2/intobject.rs new file mode 100644 index 00000000..1cb26f64 --- /dev/null +++ b/src/ffi2/intobject.rs @@ -0,0 +1,69 @@ +use libc::size_t; +use std::os::raw::{c_char, c_int, c_long, c_ulong, c_ulonglong}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyIntObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_ival: c_long +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyInt_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyInt_Check(op : *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_INT_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyInt_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyInt_Type; + (Py_TYPE(op) == u) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyInt_FromString(str: *mut c_char, + pend: *mut *mut c_char, + base: c_int) -> *mut PyObject; + #[cfg(py_sys_config="Py_USING_UNICODE")] + pub fn PyInt_FromUnicode(u: *mut ::ffi2::unicodeobject::Py_UNICODE, + length: Py_ssize_t, + base: c_int) -> *mut PyObject; + pub fn PyInt_FromLong(ival: c_long) -> *mut PyObject; + pub fn PyInt_FromSize_t(ival: size_t) -> *mut PyObject; + pub fn PyInt_FromSsize_t(ival: Py_ssize_t) -> *mut PyObject; + pub fn PyInt_AsLong(io: *mut PyObject) -> c_long; + pub fn PyInt_AsSsize_t(io: *mut PyObject) -> Py_ssize_t; + fn _PyInt_AsInt(io: *mut PyObject) -> c_int; + pub fn PyInt_AsUnsignedLongMask(io: *mut PyObject) -> c_ulong; + pub fn PyInt_AsUnsignedLongLongMask(io: *mut PyObject) + -> c_ulonglong; + pub fn PyInt_GetMax() -> c_long; + //fn PyOS_strtoul(arg1: *mut c_char, + // arg2: *mut *mut c_char, arg3: c_int) + // -> c_ulong; + //fn PyOS_strtol(arg1: *mut c_char, + // arg2: *mut *mut c_char, arg3: c_int) + // -> c_long; + pub fn PyInt_ClearFreeList() -> c_int; + //fn _PyInt_Format(v: *mut PyIntObject, base: c_int, + // newstyle: c_int) -> *mut PyObject; + //fn _PyInt_FormatAdvanced(obj: *mut PyObject, + // format_spec: *mut c_char, + // format_spec_len: Py_ssize_t) + // -> *mut PyObject; +} + +pub unsafe fn PyInt_AS_LONG(io: *mut PyObject) -> c_long { + (*(io as *mut PyIntObject)).ob_ival +} + diff --git a/src/ffi2/iterobject.rs b/src/ffi2/iterobject.rs new file mode 100644 index 00000000..45bd06a6 --- /dev/null +++ b/src/ffi2/iterobject.rs @@ -0,0 +1,21 @@ +use std::os::raw::c_int; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PySeqIter_Type: PyTypeObject; + pub static mut PyCallIter_Type: PyTypeObject; + + pub fn PySeqIter_New(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyCallIter_New(arg1: *mut PyObject, arg2: *mut PyObject) + -> *mut PyObject; +} + +#[inline(always)] +pub unsafe fn PySeqIter_Check(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PySeqIter_Type) as c_int +} + +#[inline(always)] +pub unsafe fn PyCallIter_Check(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyCallIter_Type) as c_int +} diff --git a/src/ffi2/listobject.rs b/src/ffi2/listobject.rs new file mode 100644 index 00000000..2724e4e6 --- /dev/null +++ b/src/ffi2/listobject.rs @@ -0,0 +1,74 @@ +use std::os::raw::c_int; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyListObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_size: Py_ssize_t, + pub ob_item: *mut *mut PyObject, + pub allocated: Py_ssize_t, +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyList_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyList_Check(op : *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyList_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyList_Type; + (Py_TYPE(op) == u) as c_int +} + + +// Macro, trading safety for speed +#[inline(always)] +pub unsafe fn PyList_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { + *(*(op as *mut PyListObject)).ob_item.offset(i as isize) +} + +#[inline(always)] +pub unsafe fn PyList_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { + Py_SIZE(op) +} + +/// Macro, *only* to be used to fill in brand new lists +#[inline(always)] +pub unsafe fn PyList_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { + *(*(op as *mut PyListObject)).ob_item.offset(i as isize) = v; +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyList_New(size: Py_ssize_t) -> *mut PyObject; + pub fn PyList_Size(list: *mut PyObject) -> Py_ssize_t; + pub fn PyList_GetItem(list: *mut PyObject, index: Py_ssize_t) + -> *mut PyObject; + pub fn PyList_SetItem(list: *mut PyObject, index: Py_ssize_t, + item: *mut PyObject) -> c_int; + pub fn PyList_Insert(list: *mut PyObject, index: Py_ssize_t, + item: *mut PyObject) -> c_int; + pub fn PyList_Append(list: *mut PyObject, item: *mut PyObject) + -> c_int; + pub fn PyList_GetSlice(list: *mut PyObject, low: Py_ssize_t, + high: Py_ssize_t) -> *mut PyObject; + pub fn PyList_SetSlice(list: *mut PyObject, low: Py_ssize_t, + high: Py_ssize_t, itemlist: *mut PyObject) + -> c_int; + pub fn PyList_Sort(list: *mut PyObject) -> c_int; + pub fn PyList_Reverse(list: *mut PyObject) -> c_int; + pub fn PyList_AsTuple(list: *mut PyObject) -> *mut PyObject; + //fn _PyList_Extend(arg1: *mut PyListObject, arg2: *mut PyObject) + //-> *mut PyObject; +} + diff --git a/src/ffi2/longobject.rs b/src/ffi2/longobject.rs new file mode 100644 index 00000000..3d13c58b --- /dev/null +++ b/src/ffi2/longobject.rs @@ -0,0 +1,83 @@ +use std::os::raw::{c_void, c_char, c_int, c_long, c_ulong, c_longlong, c_ulonglong, c_double}; +use libc::size_t; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +//enum PyLongObject { /* representation hidden */ } + + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyLong_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyLong_Check(op : *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyLong_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyLong_Type; + (Py_TYPE(op) == u) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyLong_FromLong(v: c_long) -> *mut PyObject; + pub fn PyLong_FromUnsignedLong(v: c_ulong) -> *mut PyObject; + pub fn PyLong_FromSsize_t(v: Py_ssize_t) -> *mut PyObject; + pub fn PyLong_FromSize_t(v: size_t) -> *mut PyObject; + pub fn PyLong_FromLongLong(v: c_longlong) -> *mut PyObject; + pub fn PyLong_FromUnsignedLongLong(v: c_ulonglong) + -> *mut PyObject; + pub fn PyLong_FromDouble(v: c_double) -> *mut PyObject; + pub fn PyLong_FromString(str: *mut c_char, + pend: *mut *mut c_char, + base: c_int) -> *mut PyObject; + #[cfg(py_sys_config="Py_USING_UNICODE")] + pub fn PyLong_FromUnicode(u: *mut ::ffi2::unicodeobject::Py_UNICODE, + length: Py_ssize_t, base: c_int) -> *mut PyObject; + pub fn PyLong_FromVoidPtr(p: *mut c_void) -> *mut PyObject; + + pub fn PyLong_AsLong(pylong: *mut PyObject) -> c_long; + pub fn PyLong_AsLongAndOverflow(pylong: *mut PyObject, + overflow: *mut c_int) + -> c_long; + pub fn PyLong_AsLongLongAndOverflow(pylong: *mut PyObject, + overflow: *mut c_int) + -> c_longlong; + pub fn PyLong_AsSsize_t(pylong: *mut PyObject) -> Py_ssize_t; + pub fn PyLong_AsUnsignedLong(pylong: *mut PyObject) -> c_ulong; + pub fn PyLong_AsLongLong(pylong: *mut PyObject) -> c_longlong; + pub fn PyLong_AsUnsignedLongLong(pylong: *mut PyObject) + -> c_ulonglong; + pub fn PyLong_AsUnsignedLongMask(pylong: *mut PyObject) -> c_ulong; + pub fn PyLong_AsUnsignedLongLongMask(pylong: *mut PyObject) + -> c_ulonglong; + pub fn PyLong_AsDouble(pylong: *mut PyObject) -> c_double; + pub fn PyLong_AsVoidPtr(pylong: *mut PyObject) -> *mut c_void; + + pub fn PyLong_GetInfo() -> *mut PyObject; + + /* + pub fn _PyLong_AsInt(arg1: *mut PyObject) -> c_int; + pub fn _PyLong_Frexp(a: *mut PyLongObject, e: *mut Py_ssize_t) + -> c_double; + + pub fn _PyLong_Sign(v: *mut PyObject) -> c_int; + pub fn _PyLong_NumBits(v: *mut PyObject) -> size_t; + pub fn _PyLong_FromByteArray(bytes: *const c_uchar, n: size_t, + little_endian: c_int, + is_signed: c_int) -> *mut PyObject; + pub fn _PyLong_AsByteArray(v: *mut PyLongObject, + bytes: *mut c_uchar, n: size_t, + little_endian: c_int, + is_signed: c_int) -> c_int; + pub fn _PyLong_Format(aa: *mut PyObject, base: c_int, + addL: c_int, newstyle: c_int) + -> *mut PyObject; + pub fn _PyLong_FormatAdvanced(obj: *mut PyObject, + format_spec: *mut c_char, + format_spec_len: Py_ssize_t) + -> *mut PyObject;*/ +} + diff --git a/src/ffi2/memoryobject.rs b/src/ffi2/memoryobject.rs new file mode 100644 index 00000000..4fded996 --- /dev/null +++ b/src/ffi2/memoryobject.rs @@ -0,0 +1,46 @@ +use std::os::raw::{c_int, c_char}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyMemoryView_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyMemoryView_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyMemoryView_Type; + (Py_TYPE(op) == u) as c_int +} + +#[inline(always)] +pub unsafe fn PyMemoryView_GET_BUFFER(op : *mut PyObject) -> *mut Py_buffer { + &mut (*(op as *mut PyMemoryViewObject)).view +} + +#[inline(always)] +pub unsafe fn PyMemoryView_GET_BASE(op : *mut PyObject) -> *mut PyObject { + (*(op as *mut PyMemoryViewObject)).view.obj +} + + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyMemoryView_GetContiguous(base: *mut PyObject, + buffertype: c_int, + fort: c_char) -> *mut PyObject; + pub fn PyMemoryView_FromObject(base: *mut PyObject) -> *mut PyObject; + pub fn PyMemoryView_FromBuffer(info: *mut Py_buffer) -> *mut PyObject; +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyMemoryViewObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub base: *mut PyObject, + pub view: Py_buffer, +} + diff --git a/src/ffi2/methodobject.rs b/src/ffi2/methodobject.rs new file mode 100644 index 00000000..6d324e13 --- /dev/null +++ b/src/ffi2/methodobject.rs @@ -0,0 +1,115 @@ +use std::ptr; +use std::os::raw::{c_char, c_int}; +use ffi2::object::{PyObject, PyTypeObject, Py_TYPE}; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyCFunction_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyCFunction_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyCFunction_Type; + (Py_TYPE(op) == u) as c_int +} + +pub type PyCFunction = + unsafe extern "C" fn + (slf: *mut PyObject, args: *mut PyObject) + -> *mut PyObject; +pub type PyCFunctionWithKeywords = + unsafe extern "C" fn + (slf: *mut PyObject, args: *mut PyObject, + kwds: *mut PyObject) -> *mut PyObject; +pub type PyNoArgsFunction = + unsafe extern "C" fn(slf: *mut PyObject) + -> *mut PyObject; + + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyCFunction_GetFunction(f: *mut PyObject) -> Option; + pub fn PyCFunction_GetSelf(f: *mut PyObject) -> *mut PyObject; + pub fn PyCFunction_GetFlags(f: *mut PyObject) -> c_int; + pub fn PyCFunction_Call(f: *mut PyObject, args: *mut PyObject, + kwds: *mut PyObject) -> *mut PyObject; +} + +#[repr(C)] +#[derive(Copy)] +pub struct PyMethodDef { + pub ml_name: *const c_char, + pub ml_meth: Option, + pub ml_flags: c_int, + pub ml_doc: *const c_char, +} + +pub const PyMethodDef_INIT : PyMethodDef = PyMethodDef { + ml_name: 0 as *const _, + ml_meth: None, + ml_flags: 0, + ml_doc: 0 as *const _, +}; + +impl Clone for PyMethodDef { + #[inline] fn clone(&self) -> PyMethodDef { *self } +} + +/* Flag passed to newmethodobject */ +pub const METH_OLDARGS : c_int = 0x0000; +pub const METH_VARARGS : c_int = 0x0001; +pub const METH_KEYWORDS : c_int = 0x0002; +/* METH_NOARGS and METH_O must not be combined with the flags above. */ +pub const METH_NOARGS : c_int = 0x0004; +pub const METH_O : c_int = 0x0008; + +/* METH_CLASS and METH_STATIC are a little different; these control + the construction of methods for a class. These cannot be used for + functions in modules. */ +pub const METH_CLASS : c_int = 0x0010; +pub const METH_STATIC : c_int = 0x0020; + +/* METH_COEXIST allows a method to be entered eventhough a slot has + already filled the entry. When defined, the flag allows a separate + method, "__contains__" for example, to coexist with a defined + slot like sq_contains. */ + +pub const METH_COEXIST : c_int = 0x0040; + + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyMethodChain { + pub methods: *mut PyMethodDef, + pub link: *mut PyMethodChain, +} + +/* +#[repr(C)] +#[derive(Copy)] +struct PyCFunctionObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub m_ml: *mut PyMethodDef, + pub m_self: *mut PyObject, + pub m_module: *mut PyObject, +} +*/ + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn Py_FindMethod(methods: *mut PyMethodDef, slf: *mut PyObject, + name: *const c_char) -> *mut PyObject; + pub fn PyCFunction_NewEx(ml: *mut PyMethodDef, slf: *mut PyObject, + module: *mut PyObject) -> *mut PyObject; + pub fn Py_FindMethodInChain(chain: *mut PyMethodChain, slf: *mut PyObject, + name: *const c_char) -> *mut PyObject; + pub fn PyCFunction_ClearFreeList() -> c_int; +} + +#[inline(always)] +pub unsafe fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject { + PyCFunction_NewEx(ml, slf, ptr::null_mut()) +} + diff --git a/src/ffi2/mod.rs b/src/ffi2/mod.rs new file mode 100644 index 00000000..207fc6db --- /dev/null +++ b/src/ffi2/mod.rs @@ -0,0 +1,138 @@ +#![no_std] +#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] + +use std::os::raw::c_int; + +pub use self::pyport::*; +pub use self::pymem::*; +pub use self::object::*; +pub use self::objimpl::*; +pub use self::pydebug::*; +#[cfg(py_sys_config="Py_USING_UNICODE")] +pub use self::unicodeobject::*; +pub use self::intobject::*; +pub use self::boolobject::*; +pub use self::longobject::*; +pub use self::floatobject::*; +pub use self::complexobject::*; +pub use self::rangeobject::*; +pub use self::memoryobject::*; +pub use self::bufferobject::*; +pub use self::stringobject::*; +pub use self::bytesobject::*; +pub use self::bytearrayobject::*; +pub use self::tupleobject::*; +pub use self::listobject::*; +pub use self::dictobject::*; +pub use self::enumobject::*; +pub use self::setobject::*; +pub use self::pyerrors::*; +pub use self::pystate::*; +pub use self::pystate::PyGILState_STATE::*; +pub use self::methodobject::*; +pub use self::moduleobject::*; +pub use self::funcobject::*; +pub use self::classobject::*; +pub use self::fileobject::*; +pub use self::cobject::*; +pub use self::pycapsule::*; +pub use self::traceback::*; +pub use self::sliceobject::*; +pub use self::cellobject::*; +pub use self::iterobject::*; +pub use self::genobject::*; +pub use self::descrobject::*; +pub use self::warnings::*; +pub use self::weakrefobject::*; +pub use self::pyarena::*; +pub use self::modsupport::*; +pub use self::pythonrun::*; +pub use self::ceval::*; +pub use self::import::*; +pub use self::objectabstract::*; +pub use self::code::*; +pub use self::compile::*; +pub use self::eval::*; +pub use self::structmember::PyMemberDef; +pub use self::frameobject::PyFrameObject; + +mod pyport; +mod pymem; +mod object; +mod objimpl; +mod pydebug; +#[cfg(py_sys_config="Py_USING_UNICODE")] +mod unicodeobject; // TODO: incomplete +mod intobject; +mod boolobject; +mod longobject; +mod floatobject; +mod complexobject; +mod rangeobject; +mod stringobject; +mod memoryobject; +mod bufferobject; +mod bytesobject; +mod bytearrayobject; +mod tupleobject; +mod listobject; +mod dictobject; +mod enumobject; +mod setobject; +mod methodobject; +mod moduleobject; +mod funcobject; +mod classobject; +mod fileobject; +mod cobject; +mod pycapsule; +mod traceback; +mod sliceobject; +mod cellobject; +mod iterobject; +mod genobject; +mod descrobject; +mod warnings; +mod weakrefobject; + +// mod codecs; // TODO: incomplete +mod pyerrors; + +mod pystate; + +mod pyarena; +mod modsupport; +mod pythonrun; +mod ceval; +// mod sysmodule; // TODO: incomplete +// mod intrcheck; // TODO: incomplete +mod import; + +mod objectabstract; + +mod code; +mod compile; +mod eval; + +// mod pyctype; // TODO: incomplete +// mod pystrtod; // TODO: incomplete +// mod pystrcmp; // TODO: incomplete +// mod dtoa; // TODO: incomplete + +// mod pyfpe; // TODO: incomplete + +// Additional headers that are not exported by Python.h +pub mod structmember; +pub mod frameobject; + +pub const Py_single_input: c_int = 256; +pub const Py_file_input: c_int = 257; +pub const Py_eval_input: c_int = 258; + +#[cfg(not(py_sys_config="Py_USING_UNICODE"))] +#[inline(always)] +pub fn PyUnicode_Check(op : *mut PyObject) -> libc::c_int { 0 } + +#[cfg(not(py_sys_config="Py_USING_UNICODE"))] +#[inline(always)] +pub fn PyUnicode_CheckExact(op : *mut PyObject) -> libc::c_int { 0 } diff --git a/src/ffi2/modsupport.rs b/src/ffi2/modsupport.rs new file mode 100644 index 00000000..c1450dbc --- /dev/null +++ b/src/ffi2/modsupport.rs @@ -0,0 +1,94 @@ +use std::ptr; +use std::os::raw::{c_char, c_int, c_long}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::PyObject; +use ffi2::methodobject::PyMethodDef; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyArg_Parse(args: *mut PyObject, format: *const c_char, ...) -> c_int; + pub fn PyArg_ParseTuple(args: *mut PyObject, + format: *const c_char, ...) -> c_int; + pub fn PyArg_ParseTupleAndKeywords(args: *mut PyObject, + kw: *mut PyObject, + format: *const c_char, + keywords: *mut *mut c_char, ...) -> c_int; + pub fn PyArg_UnpackTuple(args: *mut PyObject, name: *const c_char, + min: Py_ssize_t, max: Py_ssize_t, ...) -> c_int; + pub fn Py_BuildValue(format: *const c_char, ...) -> *mut PyObject; + //fn _Py_BuildValue_SizeT(arg1: *const c_char, ...) + // -> *mut PyObject; + //fn _PyArg_NoKeywords(funcname: *const c_char, + // kw: *mut PyObject) -> c_int; + pub fn PyModule_AddObject(module: *mut PyObject, + name: *const c_char, + value: *mut PyObject) -> c_int; + pub fn PyModule_AddIntConstant(module: *mut PyObject, + name: *const c_char, + value: c_long) -> c_int; + pub fn PyModule_AddStringConstant(module: *mut PyObject, + name: *const c_char, + value: *const c_char) -> c_int; + + #[cfg(all(target_pointer_width = "64", not(py_sys_config = "Py_TRACE_REFS")))] + fn Py_InitModule4_64(name: *const c_char, + methods: *mut PyMethodDef, + doc: *const c_char, _self: *mut PyObject, + apiver: c_int) -> *mut PyObject; + + #[cfg(all(target_pointer_width = "64", py_sys_config = "Py_TRACE_REFS"))] + fn Py_InitModule4TraceRefs_64(name: *const c_char, + methods: *mut PyMethodDef, + doc: *const c_char, _self: *mut PyObject, + apiver: c_int) -> *mut PyObject; + + #[cfg(all(not(target_pointer_width = "64"), not(py_sys_config = "Py_TRACE_REFS")))] + pub fn Py_InitModule4(name: *const c_char, + methods: *mut PyMethodDef, + doc: *const c_char, _self: *mut PyObject, + apiver: c_int) -> *mut PyObject; + + #[cfg(all(not(target_pointer_width = "64"), py_sys_config = "Py_TRACE_REFS"))] + fn Py_InitModule4TraceRefs(name: *const c_char, + methods: *mut PyMethodDef, + doc: *const c_char, _self: *mut PyObject, + apiver: c_int) -> *mut PyObject; +} + +pub const PYTHON_API_VERSION : c_int = 1013; + +#[cfg(all(target_pointer_width = "64", not(py_sys_config = "Py_TRACE_REFS")))] +#[inline(always)] +pub unsafe fn Py_InitModule4(name: *const c_char, + methods: *mut PyMethodDef, + doc: *const c_char, _self: *mut PyObject, + apiver: c_int) -> *mut PyObject { + Py_InitModule4_64(name, methods, doc, _self, apiver) +} + +#[cfg(all(target_pointer_width = "64", py_sys_config = "Py_TRACE_REFS"))] +#[inline(always)] +pub unsafe fn Py_InitModule4(name: *const c_char, + methods: *mut PyMethodDef, + doc: *const c_char, _self: *mut PyObject, + apiver: c_int) -> *mut PyObject { + Py_InitModule4TraceRefs_64(name, methods, doc, _self, apiver) +} + +#[cfg(all(not(target_pointer_width = "64"), py_sys_config = "Py_TRACE_REFS"))] +#[inline(always)] +pub unsafe fn Py_InitModule4(name: *const c_char, + methods: *mut PyMethodDef, + doc: *const c_char, _self: *mut PyObject, + apiver: c_int) -> *mut PyObject { + Py_InitModule4TraceRefs(name, methods, doc, _self, apiver) +} + +#[inline(always)] +pub unsafe fn Py_InitModule(name: *const c_char, methods: *mut PyMethodDef) -> *mut PyObject { + Py_InitModule4(name, methods, ptr::null(), ptr::null_mut(), PYTHON_API_VERSION) +} + +#[inline(always)] +pub unsafe fn Py_InitModule3(name: *const c_char, methods: *mut PyMethodDef, doc : *const c_char) -> *mut PyObject { + Py_InitModule4(name, methods, doc, ptr::null_mut(), PYTHON_API_VERSION) +} diff --git a/src/ffi2/moduleobject.rs b/src/ffi2/moduleobject.rs new file mode 100644 index 00000000..18dd1af1 --- /dev/null +++ b/src/ffi2/moduleobject.rs @@ -0,0 +1,93 @@ +use std::os::raw::{c_char, c_int, c_void}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; +use ffi2::methodobject::PyMethodDef; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyModule_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyModule_Check(op : *mut PyObject) -> c_int { + PyObject_TypeCheck(op, &mut PyModule_Type) +} + +#[inline(always)] +pub unsafe fn PyModule_CheckExact(op : *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyModule_Type) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyModule_NewObject(name: *mut PyObject) -> *mut PyObject; + pub fn PyModule_New(name: *const c_char) -> *mut PyObject; + pub fn PyModule_GetDict(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyModule_GetNameObject(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyModule_GetName(arg1: *mut PyObject) -> *const c_char; + pub fn PyModule_GetFilename(arg1: *mut PyObject) -> *const c_char; + pub fn PyModule_GetFilenameObject(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyModule_GetDef(arg1: *mut PyObject) -> *mut PyModuleDef; + pub fn PyModule_GetState(arg1: *mut PyObject) -> *mut c_void; + pub fn PyModuleDef_Init(arg1: *mut PyModuleDef) -> *mut PyObject; + pub static mut PyModuleDef_Type: PyTypeObject; +} + +#[repr(C)] +#[derive(Copy)] +pub struct PyModuleDef_Base { + pub ob_base: PyObject, + pub m_init: Option *mut PyObject>, + pub m_index: Py_ssize_t, + pub m_copy: *mut PyObject, +} +impl Clone for PyModuleDef_Base { + fn clone(&self) -> PyModuleDef_Base { *self } +} + +pub const PyModuleDef_HEAD_INIT: PyModuleDef_Base = PyModuleDef_Base { + ob_base: PyObject_HEAD_INIT, + m_init: None, + m_index: 0, + m_copy: 0 as *mut PyObject +}; + +#[repr(C)] +#[derive(Copy)] +pub struct PyModuleDef_Slot { + pub slot: c_int, + pub value: *mut c_void, +} +impl Clone for PyModuleDef_Slot { + fn clone(&self) -> PyModuleDef_Slot { *self } +} + +pub const Py_mod_create : c_int = 1; +pub const Py_mod_exec : c_int = 2; + +#[repr(C)] +#[derive(Copy)] +pub struct PyModuleDef { + pub m_base: PyModuleDef_Base, + pub m_name: *const c_char, + pub m_doc: *const c_char, + pub m_size: Py_ssize_t, + pub m_methods: *mut PyMethodDef, + pub m_slots: *mut PyModuleDef_Slot, + pub m_traverse: Option, + pub m_clear: Option, + pub m_free: Option, +} +impl Clone for PyModuleDef { + fn clone(&self) -> PyModuleDef { *self } +} + +pub const PyModuleDef_INIT: PyModuleDef = PyModuleDef { + m_base: PyModuleDef_HEAD_INIT, + m_name: 0 as *const _, + m_doc: 0 as *const _, + m_size: 0, + m_methods: 0 as *mut _, + m_slots: 0 as *mut _, + m_traverse: None, + m_clear: None, + m_free: None +}; diff --git a/src/ffi2/object.rs b/src/ffi2/object.rs new file mode 100644 index 00000000..23c6623a --- /dev/null +++ b/src/ffi2/object.rs @@ -0,0 +1,863 @@ +use std::ptr; +use std::os::raw::{c_void, c_int, c_uint, c_long, c_char, c_double}; +use libc::FILE; +use ffi2; +use ffi2::pyport::{Py_ssize_t, Py_hash_t}; +use ffi2::methodobject::PyMethodDef; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, +} + +#[cfg(py_sys_config="Py_TRACE_REFS")] +pub const PyObject_HEAD_INIT: PyObject = PyObject { + _ob_next: 0 as *mut PyObject, + _ob_prev: 0 as *mut PyObject, + ob_refcnt: 1, + ob_type: 0 as *mut PyTypeObject +}; + +#[cfg(not(py_sys_config="Py_TRACE_REFS"))] +pub const PyObject_HEAD_INIT: PyObject = PyObject { + ob_refcnt: 1, + ob_type: 0 as *mut PyTypeObject +}; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyVarObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_size: Py_ssize_t, +} + +#[inline(always)] +pub unsafe fn Py_REFCNT(ob : *mut PyObject) -> Py_ssize_t { + (*ob).ob_refcnt +} + +#[inline(always)] +pub unsafe fn Py_TYPE(ob : *mut PyObject) -> *mut PyTypeObject { + (*ob).ob_type +} + +#[inline(always)] +pub unsafe fn Py_SIZE(ob : *mut PyObject) -> Py_ssize_t { + (*(ob as *mut PyVarObject)).ob_size +} + +pub type unaryfunc = + unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; +pub type binaryfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; +pub type ternaryfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> *mut PyObject; +pub type inquiry = + unsafe extern "C" fn(arg1: *mut PyObject) -> c_int; +pub type lenfunc = + unsafe extern "C" fn(arg1: *mut PyObject) -> Py_ssize_t; +pub type coercion = + unsafe extern "C" fn (arg1: *mut *mut PyObject, + arg2: *mut *mut PyObject) -> c_int; +pub type ssizeargfunc = + unsafe extern "C" fn(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; +pub type ssizessizeargfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: Py_ssize_t, + arg3: Py_ssize_t) -> *mut PyObject; +pub type intobjargproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: c_int, arg3: *mut PyObject) -> c_int; +pub type intintobjargproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: c_int, + arg3: c_int, arg4: *mut PyObject) -> c_int; +pub type ssizeobjargproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: Py_ssize_t, + arg3: *mut PyObject) -> c_int; +pub type ssizessizeobjargproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: Py_ssize_t, + arg3: Py_ssize_t, arg4: *mut PyObject) -> c_int; +pub type objobjargproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> c_int; +pub type getreadbufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: c_int, + arg3: *mut *mut c_void) -> c_int; +pub type getwritebufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: c_int, + arg3: *mut *mut c_void) -> c_int; +pub type getsegcountproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut c_int) -> c_int; +pub type getcharbufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: c_int, arg3: *mut *mut c_char) -> c_int; +pub type readbufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: Py_ssize_t, + arg3: *mut *mut c_void) -> Py_ssize_t; +pub type writebufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: Py_ssize_t, + arg3: *mut *mut c_void) -> Py_ssize_t; +pub type segcountproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> Py_ssize_t; +pub type charbufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: Py_ssize_t, + arg3: *mut *mut c_char) -> Py_ssize_t; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Py_buffer { + pub buf: *mut c_void, + pub obj: *mut PyObject, + pub len: Py_ssize_t, + pub itemsize: Py_ssize_t, + pub readonly: c_int, + pub ndim: c_int, + pub format: *mut c_char, + pub shape: *mut Py_ssize_t, + pub strides: *mut Py_ssize_t, + pub suboffsets: *mut Py_ssize_t, + pub smalltable: [Py_ssize_t; 2], + pub internal: *mut c_void, +} + +pub type getbufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut Py_buffer, + arg3: c_int) -> c_int; +pub type releasebufferproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut Py_buffer); + +// flags: +pub const PyBUF_SIMPLE : c_int = 0; +pub const PyBUF_WRITABLE : c_int = 0x0001; +pub const PyBUF_FORMAT : c_int = 0x0004; +pub const PyBUF_ND : c_int = 0x0008; +pub const PyBUF_STRIDES : c_int = (0x0010 | PyBUF_ND); +pub const PyBUF_C_CONTIGUOUS : c_int = (0x0020 | PyBUF_STRIDES); +pub const PyBUF_F_CONTIGUOUS : c_int = (0x0040 | PyBUF_STRIDES); +pub const PyBUF_ANY_CONTIGUOUS : c_int = (0x0080 | PyBUF_STRIDES); +pub const PyBUF_INDIRECT : c_int = (0x0100 | PyBUF_STRIDES); + +pub const PyBUF_CONTIG : c_int = (PyBUF_ND | PyBUF_WRITABLE); +pub const PyBUF_CONTIG_RO : c_int = (PyBUF_ND); + +pub const PyBUF_STRIDED : c_int = (PyBUF_STRIDES | PyBUF_WRITABLE); +pub const PyBUF_STRIDED_RO : c_int = (PyBUF_STRIDES); + +pub const PyBUF_RECORDS : c_int = (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT); +pub const PyBUF_RECORDS_RO : c_int = (PyBUF_STRIDES | PyBUF_FORMAT); + +pub const PyBUF_FULL : c_int = (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT); +pub const PyBUF_FULL_RO : c_int = (PyBUF_INDIRECT | PyBUF_FORMAT); + +// buffertype: +pub const PyBUF_READ : c_int = 0x100; +pub const PyBUF_WRITE : c_int = 0x200; +pub const PyBUF_SHADOW : c_int = 0x400; + + +pub type objobjproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; +pub type visitproc = + unsafe extern "C" fn (object: *mut PyObject, arg: *mut c_void) -> c_int; +pub type traverseproc = + unsafe extern "C" fn (slf: *mut PyObject, visit: visitproc, arg: *mut c_void) -> c_int; + + +#[repr(C)] +#[derive(Copy)] +pub struct PyNumberMethods { + pub nb_add: Option, + pub nb_subtract: Option, + pub nb_multiply: Option, + pub nb_divide: Option, + pub nb_remainder: Option, + pub nb_divmod: Option, + pub nb_power: Option, + pub nb_negative: Option, + pub nb_positive: Option, + pub nb_absolute: Option, + pub nb_nonzero: Option, + pub nb_invert: Option, + pub nb_lshift: Option, + pub nb_rshift: Option, + pub nb_and: Option, + pub nb_xor: Option, + pub nb_or: Option, + pub nb_coerce: Option, + pub nb_c_int: Option, + pub nb_long: Option, + pub nb_float: Option, + pub nb_oct: Option, + pub nb_hex: Option, + pub nb_inplace_add: Option, + pub nb_inplace_subtract: Option, + pub nb_inplace_multiply: Option, + pub nb_inplace_divide: Option, + pub nb_inplace_remainder: Option, + pub nb_inplace_power: Option, + pub nb_inplace_lshift: Option, + pub nb_inplace_rshift: Option, + pub nb_inplace_and: Option, + pub nb_inplace_xor: Option, + pub nb_inplace_or: Option, + pub nb_floor_divide: Option, + pub nb_true_divide: Option, + pub nb_inplace_floor_divide: Option, + pub nb_inplace_true_divide: Option, + pub nb_index: Option, +} + +impl Clone for PyNumberMethods { + #[inline] fn clone(&self) -> PyNumberMethods { *self } +} + +pub const PyNumberMethods_INIT : PyNumberMethods = PyNumberMethods { + nb_add: None, + nb_subtract: None, + nb_multiply: None, + nb_divide: None, + nb_remainder: None, + nb_divmod: None, + nb_power: None, + nb_negative: None, + nb_positive: None, + nb_absolute: None, + nb_nonzero: None, + nb_invert: None, + nb_lshift: None, + nb_rshift: None, + nb_and: None, + nb_xor: None, + nb_or: None, + nb_coerce: None, + nb_c_int: None, + nb_long: None, + nb_float: None, + nb_oct: None, + nb_hex: None, + nb_inplace_add: None, + nb_inplace_subtract: None, + nb_inplace_multiply: None, + nb_inplace_divide: None, + nb_inplace_remainder: None, + nb_inplace_power: None, + nb_inplace_lshift: None, + nb_inplace_rshift: None, + nb_inplace_and: None, + nb_inplace_xor: None, + nb_inplace_or: None, + nb_floor_divide: None, + nb_true_divide: None, + nb_inplace_floor_divide: None, + nb_inplace_true_divide: None, + nb_index: None, +}; + +#[repr(C)] +#[derive(Copy)] +pub struct PySequenceMethods { + pub sq_length: Option, + pub sq_concat: Option, + pub sq_repeat: Option, + pub sq_item: Option, + pub sq_slice: Option, + pub sq_ass_item: Option, + pub sq_ass_slice: Option, + pub sq_contains: Option, + pub sq_inplace_concat: Option, + pub sq_inplace_repeat: Option, +} + +impl Clone for PySequenceMethods { + #[inline] fn clone(&self) -> PySequenceMethods { *self } +} + +pub const PySequenceMethods_INIT : PySequenceMethods = PySequenceMethods { + sq_length: None, + sq_concat: None, + sq_repeat: None, + sq_item: None, + sq_slice: None, + sq_ass_item: None, + sq_ass_slice: None, + sq_contains: None, + sq_inplace_concat: None, + sq_inplace_repeat: None, +}; + +#[repr(C)] +#[derive(Copy)] +pub struct PyMappingMethods { + pub mp_length: Option, + pub mp_subscript: Option, + pub mp_ass_subscript: Option, +} + +impl Clone for PyMappingMethods { + #[inline] fn clone(&self) -> PyMappingMethods { *self } +} + +pub const PyMappingMethods_INIT : PyMappingMethods = PyMappingMethods { + mp_length: None, + mp_subscript: None, + mp_ass_subscript: None, +}; + +#[repr(C)] +#[derive(Copy)] +pub struct PyBufferProcs { + pub bf_getreadbuffer: Option, + pub bf_getwritebuffer: Option, + pub bf_getsegcount: Option, + pub bf_getcharbuffer: Option, + pub bf_getbuffer: Option, + pub bf_releasebuffer: Option, +} + +impl Clone for PyBufferProcs { + #[inline] fn clone(&self) -> PyBufferProcs { *self } +} + +pub const PyBufferProcs_INIT : PyBufferProcs = PyBufferProcs { + bf_getreadbuffer: None, + bf_getwritebuffer: None, + bf_getsegcount: None, + bf_getcharbuffer: None, + bf_getbuffer: None, + bf_releasebuffer: None, +}; + +pub type freefunc = + unsafe extern "C" fn(arg1: *mut c_void); +pub type destructor = + unsafe extern "C" fn(arg1: *mut PyObject); +pub type printfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut FILE, arg3: c_int) -> c_int; +pub type getattrfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut c_char) -> *mut PyObject; +pub type getattrofunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; +pub type setattrfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut c_char, + arg3: *mut PyObject) -> c_int; +pub type setattrofunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> c_int; +pub type cmpfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; +pub type reprfunc = + unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; +pub type hashfunc = + unsafe extern "C" fn(arg1: *mut PyObject) -> Py_hash_t; +pub type richcmpfunc = + unsafe extern "C" fn (arg1: *mut PyObject, + arg2: *mut PyObject, arg3: c_int) -> *mut PyObject; +pub type getiterfunc = + unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; +pub type iternextfunc = + unsafe extern "C" fn(arg1: *mut PyObject) -> *mut PyObject; +pub type descrgetfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> *mut PyObject; +pub type descrsetfunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> c_int; +pub type initproc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> c_int; +pub type newfunc = + unsafe extern "C" fn (arg1: *mut PyTypeObject, + arg2: *mut PyObject, arg3: *mut PyObject) -> *mut PyObject; +pub type allocfunc = + unsafe extern "C" fn (arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyObject; + +#[repr(C)] +#[derive(Copy)] +pub struct PyTypeObject { + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_size: Py_ssize_t, + pub tp_name: *const c_char, + pub tp_basicsize: Py_ssize_t, + pub tp_itemsize: Py_ssize_t, + pub tp_dealloc: Option, + pub tp_print: Option, + pub tp_getattr: Option, + pub tp_setattr: Option, + pub tp_compare: Option, + pub tp_repr: Option, + pub tp_as_number: *mut PyNumberMethods, + pub tp_as_sequence: *mut PySequenceMethods, + pub tp_as_mapping: *mut PyMappingMethods, + pub tp_hash: Option, + pub tp_call: Option, + pub tp_str: Option, + pub tp_getattro: Option, + pub tp_setattro: Option, + pub tp_as_buffer: *mut PyBufferProcs, + pub tp_flags: c_long, + pub tp_doc: *const c_char, + pub tp_traverse: Option, + pub tp_clear: Option, + pub tp_richcompare: Option, + pub tp_weaklistoffset: Py_ssize_t, + pub tp_iter: Option, + pub tp_iternext: Option, + pub tp_methods: *mut PyMethodDef, + pub tp_members: *mut ffi2::structmember::PyMemberDef, + pub tp_getset: *mut ffi2::descrobject::PyGetSetDef, + pub tp_base: *mut PyTypeObject, + pub tp_dict: *mut PyObject, + pub tp_descr_get: Option, + pub tp_descr_set: Option, + pub tp_dictoffset: Py_ssize_t, + pub tp_init: Option, + pub tp_alloc: Option, + pub tp_new: Option, + pub tp_free: Option, + pub tp_is_gc: Option, + pub tp_bases: *mut PyObject, + pub tp_mro: *mut PyObject, + pub tp_cache: *mut PyObject, + pub tp_subclasses: *mut PyObject, + pub tp_weaklist: *mut PyObject, + pub tp_del: Option, + pub tp_version_tag: c_uint, +} + +impl Clone for PyTypeObject { + #[inline] fn clone(&self) -> PyTypeObject { *self } +} + +#[cfg(py_sys_config="Py_TRACE_REFS")] +pub const PyTypeObject_INIT : PyTypeObject = PyTypeObject { + _ob_next: 0 as *mut PyObject, + _ob_prev: 0 as *mut PyObject, + ob_refcnt: 1, + ob_type: 0 as *mut PyTypeObject, + ob_size: 0, + tp_name: 0 as *const c_char, + tp_basicsize: 0, + tp_itemsize: 0, + tp_dealloc: None, + tp_print: None, + tp_getattr: None, + tp_setattr: None, + tp_compare: None, + tp_repr: None, + tp_as_number: 0 as *mut PyNumberMethods, + tp_as_sequence: 0 as *mut PySequenceMethods, + tp_as_mapping: 0 as *mut PyMappingMethods, + tp_hash: None, + tp_call: None, + tp_str: None, + tp_getattro: None, + tp_setattro: None, + tp_as_buffer: 0 as *mut PyBufferProcs, + tp_flags: Py_TPFLAGS_DEFAULT, + tp_doc: 0 as *const c_char, + tp_traverse: None, + tp_clear: None, + tp_richcompare: None, + tp_weaklistoffset: 0, + tp_iter: None, + tp_iternext: None, + tp_methods: 0 as *mut PyMethodDef, + tp_members: 0 as *mut ::structmember::PyMemberDef, + tp_getset: 0 as *mut ::descrobject::PyGetSetDef, + tp_base: 0 as *mut PyTypeObject, + tp_dict: 0 as *mut PyObject, + tp_descr_get: None, + tp_descr_set: None, + tp_dictoffset: 0, + tp_init: None, + tp_alloc: None, + tp_new: None, + tp_free: None, + tp_is_gc: None, + tp_bases: 0 as *mut PyObject, + tp_mro: 0 as *mut PyObject, + tp_cache: 0 as *mut PyObject, + tp_subclasses: 0 as *mut PyObject, + tp_weaklist: 0 as *mut PyObject, + tp_del: None, + tp_version_tag: 0, +}; + +#[cfg(not(py_sys_config="Py_TRACE_REFS"))] +pub const PyTypeObject_INIT : PyTypeObject = PyTypeObject { + ob_refcnt: 1, + ob_type: 0 as *mut PyTypeObject, + ob_size: 0, + tp_name: 0 as *const c_char, + tp_basicsize: 0, + tp_itemsize: 0, + tp_dealloc: None, + tp_print: None, + tp_getattr: None, + tp_setattr: None, + tp_compare: None, + tp_repr: None, + tp_as_number: 0 as *mut PyNumberMethods, + tp_as_sequence: 0 as *mut PySequenceMethods, + tp_as_mapping: 0 as *mut PyMappingMethods, + tp_hash: None, + tp_call: None, + tp_str: None, + tp_getattro: None, + tp_setattro: None, + tp_as_buffer: 0 as *mut PyBufferProcs, + tp_flags: Py_TPFLAGS_DEFAULT, + tp_doc: 0 as *const c_char, + tp_traverse: None, + tp_clear: None, + tp_richcompare: None, + tp_weaklistoffset: 0, + tp_iter: None, + tp_iternext: None, + tp_methods: 0 as *mut PyMethodDef, + tp_members: 0 as *mut ffi2::structmember::PyMemberDef, + tp_getset: 0 as *mut ffi2::descrobject::PyGetSetDef, + tp_base: 0 as *mut PyTypeObject, + tp_dict: 0 as *mut PyObject, + tp_descr_get: None, + tp_descr_set: None, + tp_dictoffset: 0, + tp_init: None, + tp_alloc: None, + tp_new: None, + tp_free: None, + tp_is_gc: None, + tp_bases: 0 as *mut PyObject, + tp_mro: 0 as *mut PyObject, + tp_cache: 0 as *mut PyObject, + tp_subclasses: 0 as *mut PyObject, + tp_weaklist: 0 as *mut PyObject, + tp_del: None, + tp_version_tag: 0, +}; + +#[repr(C)] +#[derive(Copy)] +pub struct PyHeapTypeObject { + pub ht_type: PyTypeObject, + pub as_number: PyNumberMethods, + pub as_mapping: PyMappingMethods, + pub as_sequence: PySequenceMethods, + pub as_buffer: PyBufferProcs, + pub ht_name: *mut PyObject, + pub ht_slots: *mut PyObject, +} + +impl Clone for PyHeapTypeObject { + #[inline] fn clone(&self) -> PyHeapTypeObject { *self } +} + +// access macro to the members which are floating "behind" the object +#[inline] +pub unsafe fn PyHeapType_GET_MEMBERS(etype: *mut PyHeapTypeObject) -> *mut ffi2::structmember::PyMemberDef { + let basicsize = (*Py_TYPE(etype as *mut PyObject)).tp_basicsize; + (etype as *mut u8).offset(basicsize as isize) as *mut ffi2::structmember::PyMemberDef +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int; +} + +#[inline(always)] +pub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int { + (Py_TYPE(ob) == tp || PyType_IsSubtype(Py_TYPE(ob), tp) != 0) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyType_Type: PyTypeObject; + pub static mut PyBaseObject_Type: PyTypeObject; + pub static mut PySuper_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == (&mut PyType_Type as *mut _)) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyType_Ready(t: *mut PyTypeObject) -> c_int; + pub fn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) -> *mut PyObject; + pub fn PyType_GenericNew(t: *mut PyTypeObject, args: *mut PyObject, + kwds: *mut PyObject) -> *mut PyObject; + fn _PyType_Lookup(arg1: *mut PyTypeObject, arg2: *mut PyObject) -> *mut PyObject; + fn _PyObject_LookupSpecial(arg1: *mut PyObject, + arg2: *mut c_char, + arg3: *mut *mut PyObject) -> *mut PyObject; + pub fn PyType_ClearCache() -> c_uint; + pub fn PyType_Modified(t: *mut PyTypeObject); + + pub fn PyObject_Print(o: *mut PyObject, fp: *mut FILE, + flags: c_int) -> c_int; + fn _PyObject_Dump(o: *mut PyObject); + pub fn PyObject_Repr(o: *mut PyObject) -> *mut PyObject; + fn _PyObject_Str(o: *mut PyObject) -> *mut PyObject; + pub fn PyObject_Str(o: *mut PyObject) -> *mut PyObject; +} + +#[inline(always)] +pub unsafe fn PyObject_Bytes(o: *mut PyObject) -> *mut PyObject { + PyObject_Str(o) +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + #[cfg(py_sys_config="Py_USING_UNICODE")] + pub fn PyObject_Unicode(o: *mut PyObject) -> *mut PyObject; + + pub fn PyObject_Compare(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; + pub fn PyObject_RichCompare(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: c_int) -> *mut PyObject; + pub fn PyObject_RichCompareBool(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: c_int) -> c_int; + pub fn PyObject_GetAttrString(arg1: *mut PyObject, + arg2: *const c_char) -> *mut PyObject; + pub fn PyObject_SetAttrString(arg1: *mut PyObject, + arg2: *const c_char, + arg3: *mut PyObject) -> c_int; + pub fn PyObject_HasAttrString(arg1: *mut PyObject, + arg2: *const c_char) -> c_int; + pub fn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; + pub fn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> c_int; + pub fn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; + fn _PyObject_GetDictPtr(arg1: *mut PyObject) -> *mut *mut PyObject; + pub fn PyObject_SelfIter(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyObject_GenericGetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; + pub fn PyObject_GenericSetAttr(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject) -> c_int; + pub fn PyObject_Hash(arg1: *mut PyObject) -> Py_hash_t; + pub fn PyObject_HashNotImplemented(arg1: *mut PyObject) -> Py_hash_t; + pub fn PyObject_IsTrue(arg1: *mut PyObject) -> c_int; + pub fn PyObject_Not(arg1: *mut PyObject) -> c_int; + pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int; + pub fn PyNumber_Coerce(arg1: *mut *mut PyObject, arg2: *mut *mut PyObject) -> c_int; + pub fn PyNumber_CoerceEx(arg1: *mut *mut PyObject, + arg2: *mut *mut PyObject) -> c_int; + pub fn PyObject_ClearWeakRefs(arg1: *mut PyObject); + fn _PyObject_SlotCompare(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; + fn _PyObject_GenericGetAttrWithDict(arg1: *mut PyObject, + arg2: *mut PyObject, + arg3: *mut PyObject) -> *mut PyObject; + fn _PyObject_GenericSetAttrWithDict(arg1: *mut PyObject, + arg2: *mut PyObject, + arg3: *mut PyObject, + arg4: *mut PyObject) -> c_int; + pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject; + pub fn Py_ReprEnter(arg1: *mut PyObject) -> c_int; + pub fn Py_ReprLeave(arg1: *mut PyObject); + fn _Py_HashDouble(arg1: c_double) -> c_long; + fn _Py_HashPointer(arg1: *mut c_void) -> c_long; +} + +// Flag bits for printing: +pub const Py_PRINT_RAW : c_int = 1; // No string quotes etc. + +/// PyBufferProcs contains bf_getcharbuffer +pub const Py_TPFLAGS_HAVE_GETCHARBUFFER : c_long = (1<<0); + +/// PySequenceMethods contains sq_contains +pub const Py_TPFLAGS_HAVE_SEQUENCE_IN : c_long = (1<<1); + +/// PySequenceMethods and PyNumberMethods contain in-place operators +pub const Py_TPFLAGS_HAVE_INPLACEOPS : c_long = (1<<3); + +/// PyNumberMethods do their own coercion +pub const Py_TPFLAGS_CHECKTYPES : c_long = (1<<4); + +/// tp_richcompare is defined +pub const Py_TPFLAGS_HAVE_RICHCOMPARE : c_long = (1<<5); + +/// Objects which are weakly referencable if their tp_weaklistoffset is >0 +pub const Py_TPFLAGS_HAVE_WEAKREFS : c_long = (1<<6); + +/// tp_iter is defined +pub const Py_TPFLAGS_HAVE_ITER : c_long = (1<<7); + +/// New members introduced by Python 2.2 exist +pub const Py_TPFLAGS_HAVE_CLASS : c_long = (1<<8); + +/// Set if the type object is dynamically allocated +pub const Py_TPFLAGS_HEAPTYPE : c_long = (1<<9); + +/// Set if the type allows subclassing +pub const Py_TPFLAGS_BASETYPE : c_long = (1<<10); + +/// Set if the type is 'ready' -- fully initialized +pub const Py_TPFLAGS_READY : c_long = (1<<12); + +/// Set while the type is being 'readied', to prevent recursive ready calls +pub const Py_TPFLAGS_READYING : c_long = (1<<13); + +/// Objects support garbage collection (see objimp.h) +pub const Py_TPFLAGS_HAVE_GC : c_long = (1<<14); + +// Two bits are preserved for Stackless Python, next after this is 17. +const Py_TPFLAGS_HAVE_STACKLESS_EXTENSION : c_long = 0; + +/// Objects support nb_index in PyNumberMethods +pub const Py_TPFLAGS_HAVE_INDEX : c_long = (1<<17); + +/// Objects support type attribute cache +pub const Py_TPFLAGS_HAVE_VERSION_TAG : c_long = (1<<18); +pub const Py_TPFLAGS_VALID_VERSION_TAG : c_long = (1<<19); + +/* Type is abstract and cannot be instantiated */ +pub const Py_TPFLAGS_IS_ABSTRACT : c_long = (1<<20); + +/* Has the new buffer protocol */ +pub const Py_TPFLAGS_HAVE_NEWBUFFER : c_long = (1<<21); + +/* These flags are used to determine if a type is a subclass. */ +pub const Py_TPFLAGS_INT_SUBCLASS : c_long = (1<<23); +pub const Py_TPFLAGS_LONG_SUBCLASS : c_long = (1<<24); +pub const Py_TPFLAGS_LIST_SUBCLASS : c_long = (1<<25); +pub const Py_TPFLAGS_TUPLE_SUBCLASS : c_long = (1<<26); +pub const Py_TPFLAGS_STRING_SUBCLASS : c_long = (1<<27); +pub const Py_TPFLAGS_UNICODE_SUBCLASS : c_long = (1<<28); +pub const Py_TPFLAGS_DICT_SUBCLASS : c_long = (1<<29); +pub const Py_TPFLAGS_BASE_EXC_SUBCLASS : c_long = (1<<30); +pub const Py_TPFLAGS_TYPE_SUBCLASS : c_long = (1<<31); + +pub const Py_TPFLAGS_DEFAULT : c_long = ( + Py_TPFLAGS_HAVE_GETCHARBUFFER | + Py_TPFLAGS_HAVE_SEQUENCE_IN | + Py_TPFLAGS_HAVE_INPLACEOPS | + Py_TPFLAGS_HAVE_RICHCOMPARE | + Py_TPFLAGS_HAVE_WEAKREFS | + Py_TPFLAGS_HAVE_ITER | + Py_TPFLAGS_HAVE_CLASS | + Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | + Py_TPFLAGS_HAVE_INDEX | + 0); + +#[inline(always)] +pub unsafe fn PyType_HasFeature(t : *mut PyTypeObject, f : c_long) -> c_int { + (((*t).tp_flags & f) != 0) as c_int +} + +#[inline(always)] +pub unsafe fn PyType_FastSubclass(t : *mut PyTypeObject, f : c_long) -> c_int { + PyType_HasFeature(t, f) +} + +// Reference counting macros. +#[inline(always)] +pub unsafe fn Py_INCREF(op : *mut PyObject) { + if cfg!(py_sys_config="Py_REF_DEBUG") { + Py_IncRef(op) + } else { + (*op).ob_refcnt += 1 + } +} + +#[inline(always)] +pub unsafe fn Py_DECREF(op: *mut PyObject) { + if cfg!(py_sys_config="Py_REF_DEBUG") || cfg!(py_sys_config="COUNT_ALLOCS") { + Py_DecRef(op) + } else { + (*op).ob_refcnt -= 1; + if (*op).ob_refcnt == 0 { + (*Py_TYPE(op)).tp_dealloc.unwrap()(op) + } + } +} + +#[inline(always)] +pub unsafe fn Py_CLEAR(op: &mut *mut PyObject) { + let tmp = *op; + if !tmp.is_null() { + *op = ptr::null_mut(); + Py_DECREF(tmp); + } +} + +#[inline(always)] +pub unsafe fn Py_XINCREF(op : *mut PyObject) { + if !op.is_null() { + Py_INCREF(op) + } +} + +#[inline(always)] +pub unsafe fn Py_XDECREF(op : *mut PyObject) { + if !op.is_null() { + Py_DECREF(op) + } +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn Py_IncRef(o: *mut PyObject); + pub fn Py_DecRef(o: *mut PyObject); + + static mut _Py_NoneStruct: PyObject; + static mut _Py_NotImplementedStruct: PyObject; +} + +#[inline(always)] +pub unsafe fn Py_None() -> *mut PyObject { + &mut _Py_NoneStruct +} + +#[inline(always)] +pub unsafe fn Py_NotImplemented() -> *mut PyObject { + &mut _Py_NotImplementedStruct +} + +/* Rich comparison opcodes */ +pub const Py_LT : c_int = 0; +pub const Py_LE : c_int = 1; +pub const Py_EQ : c_int = 2; +pub const Py_NE : c_int = 3; +pub const Py_GT : c_int = 4; +pub const Py_GE : c_int = 5; + +#[inline] +pub fn PyObject_Check(_arg1: *mut PyObject) -> c_int { + 1 +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + fn _PyTrash_thread_deposit_object(o: *mut PyObject); + fn _PyTrash_thread_destroy_chain(); +} + +pub const PyTrash_UNWIND_LEVEL : c_int = 50; + +#[inline(always)] +pub unsafe fn Py_TRASHCAN ()>(op: *mut PyObject, body: F) { + let tstate = ffi2::pystate::PyThreadState_GET(); + if tstate.is_null() || (*tstate).trash_delete_nesting < PyTrash_UNWIND_LEVEL { + if !tstate.is_null() { + (*tstate).trash_delete_nesting += 1; + } + body(); + if !tstate.is_null() { + (*tstate).trash_delete_nesting -= 1; + if !(*tstate).trash_delete_later.is_null() && (*tstate).trash_delete_nesting <= 0 { + _PyTrash_thread_destroy_chain(); + } + } + } else { + _PyTrash_thread_deposit_object(op) + } +} + diff --git a/src/ffi2/objectabstract.rs b/src/ffi2/objectabstract.rs new file mode 100644 index 00000000..3e7c349c --- /dev/null +++ b/src/ffi2/objectabstract.rs @@ -0,0 +1,309 @@ +use std::ptr; +use std::os::raw::{c_void, c_char, c_int}; +use ffi2; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[inline] +pub unsafe fn PyObject_DelAttrString(o: *mut PyObject, attr_name: *const c_char) -> c_int { + PyObject_SetAttrString(o, attr_name, ptr::null_mut()) +} + +#[inline] +pub unsafe fn PyObject_DelAttr(o: *mut PyObject, attr_name: *mut PyObject) -> c_int { + PyObject_SetAttr(o, attr_name, ptr::null_mut()) +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyObject_Cmp(o1: *mut PyObject, o2: *mut PyObject, + result: *mut c_int) -> c_int; + pub fn PyObject_Call(callable_object: *mut PyObject, args: *mut PyObject, + kw: *mut PyObject) -> *mut PyObject; + pub fn PyObject_CallObject(callable_object: *mut PyObject, + args: *mut PyObject) -> *mut PyObject; + pub fn PyObject_CallFunction(callable_object: *mut PyObject, + format: *mut c_char, ...) + -> *mut PyObject; + pub fn PyObject_CallMethod(o: *mut PyObject, m: *mut c_char, + format: *mut c_char, ...) + -> *mut PyObject; + fn _PyObject_CallFunction_SizeT(callable: *mut PyObject, + format: *mut c_char, ...) + -> *mut PyObject; + fn _PyObject_CallMethod_SizeT(o: *mut PyObject, + name: *mut c_char, + format: *mut c_char, ...) + -> *mut PyObject; + pub fn PyObject_CallFunctionObjArgs(callable: *mut PyObject, ...) + -> *mut PyObject; + pub fn PyObject_CallMethodObjArgs(o: *mut PyObject, m: *mut PyObject, ...) + -> *mut PyObject; + pub fn PyObject_Type(o: *mut PyObject) -> *mut PyObject; + pub fn PyObject_Size(o: *mut PyObject) -> Py_ssize_t; + pub fn _PyObject_LengthHint(o: *mut PyObject, arg1: Py_ssize_t) + -> Py_ssize_t; + pub fn PyObject_GetItem(o: *mut PyObject, key: *mut PyObject) + -> *mut PyObject; + pub fn PyObject_SetItem(o: *mut PyObject, key: *mut PyObject, + v: *mut PyObject) -> c_int; + pub fn PyObject_DelItemString(o: *mut PyObject, key: *mut c_char) + -> c_int; + pub fn PyObject_DelItem(o: *mut PyObject, key: *mut PyObject) + -> c_int; + pub fn PyObject_AsCharBuffer(obj: *mut PyObject, + buffer: *mut *const c_char, + buffer_len: *mut Py_ssize_t) + -> c_int; + pub fn PyObject_CheckReadBuffer(obj: *mut PyObject) -> c_int; + pub fn PyObject_AsReadBuffer(obj: *mut PyObject, + buffer: *mut *const c_void, + buffer_len: *mut Py_ssize_t) + -> c_int; + pub fn PyObject_AsWriteBuffer(obj: *mut PyObject, + buffer: *mut *mut c_void, + buffer_len: *mut Py_ssize_t) + -> c_int; + + pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, + flags: c_int) -> c_int; + + pub fn PyBuffer_GetPointer(view: *mut Py_buffer, indices: *mut Py_ssize_t) + -> *mut c_void; + pub fn PyBuffer_ToContiguous(buf: *mut c_void, + view: *mut Py_buffer, len: Py_ssize_t, + fort: c_char) -> c_int; + pub fn PyBuffer_FromContiguous(view: *mut Py_buffer, + buf: *mut c_void, len: Py_ssize_t, + fort: c_char) -> c_int; + pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) + -> c_int; + pub fn PyBuffer_IsContiguous(view: *mut Py_buffer, fort: c_char) + -> c_int; + pub fn PyBuffer_FillContiguousStrides(ndims: c_int, + shape: *mut Py_ssize_t, + strides: *mut Py_ssize_t, + itemsize: c_int, + fort: c_char); + pub fn PyBuffer_FillInfo(view: *mut Py_buffer, o: *mut PyObject, + buf: *mut c_void, len: Py_ssize_t, + readonly: c_int, flags: c_int) + -> c_int; + pub fn PyBuffer_Release(view: *mut Py_buffer); + pub fn PyObject_Format(obj: *mut PyObject, format_spec: *mut PyObject) + -> *mut PyObject; + pub fn PyObject_GetIter(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyIter_Next(arg1: *mut PyObject) -> *mut PyObject; + fn _PyObject_NextNotImplemented(arg1: *mut PyObject) -> *mut PyObject; + + pub fn PyNumber_Check(o: *mut PyObject) -> c_int; + pub fn PyNumber_Add(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Subtract(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Multiply(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Divide(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_FloorDivide(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_TrueDivide(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Remainder(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Divmod(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Power(o1: *mut PyObject, o2: *mut PyObject, + o3: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Negative(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Positive(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Absolute(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Invert(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Lshift(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Rshift(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_And(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Xor(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_Or(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Index(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_AsSsize_t(o: *mut PyObject, exc: *mut PyObject) + -> Py_ssize_t; + fn _PyNumber_ConvertIntegralToInt(integral: *mut PyObject, + error_format: *const c_char) + -> *mut PyObject; + pub fn PyNumber_Int(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Long(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_Float(o: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_InPlaceAdd(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceSubtract(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceMultiply(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceDivide(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceFloorDivide(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceTrueDivide(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceRemainder(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlacePower(o1: *mut PyObject, o2: *mut PyObject, + o3: *mut PyObject) -> *mut PyObject; + pub fn PyNumber_InPlaceLshift(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceRshift(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceAnd(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceXor(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_InPlaceOr(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PyNumber_ToBase(n: *mut PyObject, base: c_int) + -> *mut PyObject; + pub fn PySequence_Check(o: *mut PyObject) -> c_int; + pub fn PySequence_Size(o: *mut PyObject) -> Py_ssize_t; + pub fn PySequence_Length(o: *mut PyObject) -> Py_ssize_t; + pub fn PySequence_Concat(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PySequence_Repeat(o: *mut PyObject, count: Py_ssize_t) + -> *mut PyObject; + pub fn PySequence_GetItem(o: *mut PyObject, i: Py_ssize_t) + -> *mut PyObject; + pub fn PySequence_GetSlice(o: *mut PyObject, i1: Py_ssize_t, + i2: Py_ssize_t) -> *mut PyObject; + pub fn PySequence_SetItem(o: *mut PyObject, i: Py_ssize_t, + v: *mut PyObject) -> c_int; + pub fn PySequence_DelItem(o: *mut PyObject, i: Py_ssize_t) + -> c_int; + pub fn PySequence_SetSlice(o: *mut PyObject, i1: Py_ssize_t, + i2: Py_ssize_t, v: *mut PyObject) + -> c_int; + pub fn PySequence_DelSlice(o: *mut PyObject, i1: Py_ssize_t, + i2: Py_ssize_t) -> c_int; + pub fn PySequence_Tuple(o: *mut PyObject) -> *mut PyObject; + pub fn PySequence_List(o: *mut PyObject) -> *mut PyObject; + pub fn PySequence_Fast(o: *mut PyObject, m: *const c_char) + -> *mut PyObject; + pub fn PySequence_Count(o: *mut PyObject, value: *mut PyObject) + -> Py_ssize_t; + pub fn PySequence_Contains(seq: *mut PyObject, ob: *mut PyObject) + -> c_int; + pub fn _PySequence_IterSearch(seq: *mut PyObject, obj: *mut PyObject, + operation: c_int) -> Py_ssize_t; + pub fn PySequence_In(o: *mut PyObject, value: *mut PyObject) + -> c_int; + pub fn PySequence_Index(o: *mut PyObject, value: *mut PyObject) + -> Py_ssize_t; + pub fn PySequence_InPlaceConcat(o1: *mut PyObject, o2: *mut PyObject) + -> *mut PyObject; + pub fn PySequence_InPlaceRepeat(o: *mut PyObject, count: Py_ssize_t) + -> *mut PyObject; + pub fn PyMapping_Check(o: *mut PyObject) -> c_int; + pub fn PyMapping_Size(o: *mut PyObject) -> Py_ssize_t; + pub fn PyMapping_Length(o: *mut PyObject) -> Py_ssize_t; + pub fn PyMapping_HasKeyString(o: *mut PyObject, key: *mut c_char) + -> c_int; + pub fn PyMapping_HasKey(o: *mut PyObject, key: *mut PyObject) + -> c_int; + pub fn PyMapping_GetItemString(o: *mut PyObject, key: *mut c_char) + -> *mut PyObject; + pub fn PyMapping_SetItemString(o: *mut PyObject, key: *mut c_char, + value: *mut PyObject) -> c_int; + pub fn PyObject_IsInstance(object: *mut PyObject, + typeorclass: *mut PyObject) -> c_int; + pub fn PyObject_IsSubclass(object: *mut PyObject, + typeorclass: *mut PyObject) -> c_int; +} + + +#[inline] +pub unsafe fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int { + let t = (*obj).ob_type; + let b = (*t).tp_as_buffer; + (!b.is_null() && + (PyType_HasFeature(t, Py_TPFLAGS_HAVE_NEWBUFFER) != 0) && + ((*b).bf_getbuffer.is_some())) as c_int +} + + +#[inline] +pub unsafe fn PyIter_Check(obj: *mut PyObject) -> c_int { + let t = (*obj).ob_type; + (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER) != 0 && + match (*t).tp_iternext { + None => false, + Some(f) => f as *const c_void != _PyObject_NextNotImplemented as *const c_void, + }) as c_int +} + +#[inline] +pub unsafe fn PyIndex_Check(obj: *mut PyObject) -> c_int { + let t = (*obj).ob_type; + let n = (*t).tp_as_number; + (!n.is_null() && PyType_HasFeature(t, Py_TPFLAGS_HAVE_INDEX) != 0 && (*n).nb_index.is_some()) as c_int +} + +#[inline] +pub unsafe fn PySequence_Fast_GET_SIZE(o : *mut PyObject) -> Py_ssize_t { + if ffi2::listobject::PyList_Check(o) != 0 { + ffi2::listobject::PyList_GET_SIZE(o) + } else { + ffi2::tupleobject::PyTuple_GET_SIZE(o) + } +} + +#[inline] +pub unsafe fn PySequence_Fast_GET_ITEM(o : *mut PyObject, i : Py_ssize_t) -> *mut PyObject { + if ffi2::listobject::PyList_Check(o) != 0 { + ffi2::listobject::PyList_GET_ITEM(o, i) + } else { + ffi2::tupleobject::PyTuple_GET_ITEM(o, i) + } +} + +#[inline] +pub unsafe fn PySequence_Fast_ITEMS(o : *mut PyObject) -> *mut *mut PyObject { + if ffi2::listobject::PyList_Check(o) != 0 { + (*(o as *mut ffi2::listobject::PyListObject)).ob_item + } else { + (*(o as *mut ffi2::tupleobject::PyTupleObject)).ob_item.as_mut_ptr() + } +} + +#[inline] +pub unsafe fn PySequence_ITEM(o : *mut PyObject, i : Py_ssize_t) -> *mut PyObject { + (*(*Py_TYPE(o)).tp_as_sequence).sq_item.unwrap()(o, i) +} + +pub const PY_ITERSEARCH_COUNT : c_int = 1; +pub const PY_ITERSEARCH_INDEX : c_int = 2; +pub const PY_ITERSEARCH_CONTAINS : c_int = 3; + +#[inline] +pub unsafe fn PyMapping_DelItemString(o : *mut PyObject, key : *mut c_char) -> c_int { + PyObject_DelItemString(o, key) +} + +#[inline] +pub unsafe fn PyMapping_DelItem(o : *mut PyObject, key : *mut PyObject) -> c_int { + PyObject_DelItem(o, key) +} + +#[inline] +pub unsafe fn PyMapping_Keys(o : *mut PyObject) -> *mut PyObject { + PyObject_CallMethod(o, "keys\0".as_ptr() as *mut i8, ptr::null_mut()) +} + +#[inline] +pub unsafe fn PyMapping_Values(o : *mut PyObject) -> *mut PyObject { + PyObject_CallMethod(o, "values\0".as_ptr() as *mut i8, ptr::null_mut()) +} + +#[inline] +pub unsafe fn PyMapping_Items(o : *mut PyObject) -> *mut PyObject { + PyObject_CallMethod(o, "items\0".as_ptr() as *mut i8, ptr::null_mut()) +} diff --git a/src/ffi2/objimpl.rs b/src/ffi2/objimpl.rs new file mode 100644 index 00000000..62e9bfe0 --- /dev/null +++ b/src/ffi2/objimpl.rs @@ -0,0 +1,61 @@ +use std::os::raw::{c_void, c_char, c_int}; +use libc::size_t; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyObject_Malloc(arg1: size_t) -> *mut c_void; + pub fn PyObject_Realloc(arg1: *mut c_void, arg2: size_t) + -> *mut c_void; + pub fn PyObject_Free(arg1: *mut c_void); + + pub fn PyObject_Init(arg1: *mut PyObject, arg2: *mut PyTypeObject) + -> *mut PyObject; + pub fn PyObject_InitVar(arg1: *mut PyVarObject, arg2: *mut PyTypeObject, + arg3: Py_ssize_t) -> *mut PyVarObject; + pub fn _PyObject_New(arg1: *mut PyTypeObject) -> *mut PyObject; + pub fn _PyObject_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) + -> *mut PyVarObject; + + // GC Support + pub fn PyGC_Collect() -> Py_ssize_t; + pub fn _PyObject_GC_Resize(arg1: *mut PyVarObject, arg2: Py_ssize_t) + -> *mut PyVarObject; + pub fn _PyObject_GC_Malloc(arg1: size_t) -> *mut PyObject; + pub fn _PyObject_GC_New(arg1: *mut PyTypeObject) -> *mut PyObject; + pub fn _PyObject_GC_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) + -> *mut PyVarObject; + pub fn PyObject_GC_Track(arg1: *mut c_void); + pub fn PyObject_GC_UnTrack(arg1: *mut c_void); + pub fn PyObject_GC_Del(arg1: *mut c_void); +} + +/// Test if a type has a GC head +#[inline(always)] +pub unsafe fn PyType_IS_GC(t : *mut PyTypeObject) -> c_int { + PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC) +} + +/// Test if an object has a GC head +#[inline(always)] +pub unsafe fn PyObject_IS_GC(o : *mut PyObject) -> c_int { + (PyType_IS_GC(Py_TYPE(o)) != 0 && + match (*Py_TYPE(o)).tp_is_gc { + Some(tp_is_gc) => tp_is_gc(o) != 0, + None => true + }) as c_int +} + +/* Test if a type supports weak references */ +#[inline(always)] +pub unsafe fn PyType_SUPPORTS_WEAKREFS(t : *mut PyTypeObject) -> c_int { + (PyType_HasFeature((t), Py_TPFLAGS_HAVE_WEAKREFS) != 0 + && ((*t).tp_weaklistoffset > 0)) as c_int +} + +#[inline(always)] +pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o : *mut PyObject) -> *mut *mut PyObject { + let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset as isize; + (o as *mut c_char).offset(weaklistoffset) as *mut *mut PyObject +} + diff --git a/src/ffi2/pyarena.rs b/src/ffi2/pyarena.rs new file mode 100644 index 00000000..d7429d0d --- /dev/null +++ b/src/ffi2/pyarena.rs @@ -0,0 +1,13 @@ +use libc::size_t; +use std::os::raw::{c_void, c_int}; +use ffi2::object::PyObject; + +#[allow(missing_copy_implementations)] +pub enum PyArena { } + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyArena_New() -> *mut PyArena; + pub fn PyArena_Free(arg1: *mut PyArena); + pub fn PyArena_Malloc(arg1: *mut PyArena, size: size_t) -> *mut c_void; + pub fn PyArena_AddPyObject(arg1: *mut PyArena, arg2: *mut PyObject) -> c_int; +} diff --git a/src/ffi2/pycapsule.rs b/src/ffi2/pycapsule.rs new file mode 100644 index 00000000..84316530 --- /dev/null +++ b/src/ffi2/pycapsule.rs @@ -0,0 +1,36 @@ +use std::os::raw::{c_void, c_char, c_int}; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyCapsule_Type: PyTypeObject; +} + +pub type PyCapsule_Destructor = unsafe extern "C" fn(o: *mut PyObject); + +#[inline] +pub unsafe fn PyCapsule_CheckExact(ob: *mut PyObject) -> c_int { + (Py_TYPE(ob) == &mut PyCapsule_Type) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyCapsule_New(pointer: *mut c_void, + name: *const c_char, + destructor: Option) -> *mut PyObject; + pub fn PyCapsule_GetPointer(capsule: *mut PyObject, + name: *const c_char) -> *mut c_void; + pub fn PyCapsule_GetDestructor(capsule: *mut PyObject) -> Option; + pub fn PyCapsule_GetName(capsule: *mut PyObject) -> *const c_char; + pub fn PyCapsule_GetContext(capsule: *mut PyObject) -> *mut c_void; + pub fn PyCapsule_IsValid(capsule: *mut PyObject, + name: *const c_char) -> c_int; + pub fn PyCapsule_SetPointer(capsule: *mut PyObject, + pointer: *mut c_void) -> c_int; + pub fn PyCapsule_SetDestructor(capsule: *mut PyObject, + destructor: Option) -> c_int; + pub fn PyCapsule_SetName(capsule: *mut PyObject, + name: *const c_char) -> c_int; + pub fn PyCapsule_SetContext(capsule: *mut PyObject, + context: *mut c_void) -> c_int; + pub fn PyCapsule_Import(name: *const c_char, + no_block: c_int) -> *mut c_void; +} diff --git a/src/ffi2/pydebug.rs b/src/ffi2/pydebug.rs new file mode 100644 index 00000000..c54f77d2 --- /dev/null +++ b/src/ffi2/pydebug.rs @@ -0,0 +1,25 @@ +use std::os::raw::{c_char, c_int}; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut Py_DebugFlag: c_int; + pub static mut Py_VerboseFlag: c_int; + pub static mut Py_InteractiveFlag: c_int; + pub static mut Py_InspectFlag: c_int; + pub static mut Py_OptimizeFlag: c_int; + pub static mut Py_NoSiteFlag: c_int; + pub static mut Py_BytesWarningFlag: c_int; + pub static mut Py_UseClassExceptionsFlag: c_int; + pub static mut Py_FrozenFlag: c_int; + pub static mut Py_TabcheckFlag: c_int; + pub static mut Py_UnicodeFlag: c_int; + pub static mut Py_IgnoreEnvironmentFlag: c_int; + pub static mut Py_DivisionWarningFlag: c_int; + pub static mut Py_DontWriteBytecodeFlag: c_int; + pub static mut Py_NoUserSiteDirectory: c_int; + pub static mut _Py_QnewFlag: c_int; + pub static mut Py_Py3kWarningFlag: c_int; + pub static mut Py_HashRandomizationFlag: c_int; + + pub fn Py_FatalError(message: *const c_char); +} + diff --git a/src/ffi2/pyerrors.rs b/src/ffi2/pyerrors.rs new file mode 100644 index 00000000..080ccc16 --- /dev/null +++ b/src/ffi2/pyerrors.rs @@ -0,0 +1,216 @@ +use std::os::raw::{c_char, c_int}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; +use ffi2::classobject::*; +use ffi2::stringobject::PyString_AS_STRING; +#[cfg(py_sys_config="Py_USING_UNICODE")] +use ffi2::unicodeobject::Py_UNICODE; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyErr_SetNone(arg1: *mut PyObject); + pub fn PyErr_SetObject(arg1: *mut PyObject, arg2: *mut PyObject); + pub fn PyErr_SetString(arg1: *mut PyObject, arg2: *const c_char); + pub fn PyErr_Occurred() -> *mut PyObject; + pub fn PyErr_Clear(); + pub fn PyErr_Fetch(arg1: *mut *mut PyObject, arg2: *mut *mut PyObject, + arg3: *mut *mut PyObject); + pub fn PyErr_Restore(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject); + pub fn PyErr_GivenExceptionMatches(arg1: *mut PyObject, + arg2: *mut PyObject) -> c_int; + pub fn PyErr_ExceptionMatches(arg1: *mut PyObject) -> c_int; + pub fn PyErr_NormalizeException(arg1: *mut *mut PyObject, + arg2: *mut *mut PyObject, + arg3: *mut *mut PyObject); +} + +#[inline] +pub unsafe fn PyExceptionClass_Check(x: *mut PyObject) -> c_int { + (PyClass_Check((x)) != 0 || (PyType_Check((x)) != 0 && + PyType_FastSubclass(x as *mut PyTypeObject, Py_TPFLAGS_BASE_EXC_SUBCLASS) != 0)) as c_int +} + +#[inline] +pub unsafe fn PyExceptionInstance_Check(x: *mut PyObject) -> c_int { + (PyInstance_Check((x)) != 0 || + PyType_FastSubclass((*x).ob_type, Py_TPFLAGS_BASE_EXC_SUBCLASS) != 0) as c_int +} + +#[inline] +pub unsafe fn PyExceptionClass_Name(x: *mut PyObject) -> *const c_char { + if PyClass_Check(x) != 0 { + PyString_AS_STRING((*(x as *mut PyClassObject)).cl_name) + } else { + (*(x as *mut PyTypeObject)).tp_name + } +} + +#[inline] +pub unsafe fn PyExceptionInstance_Class(x: *mut PyObject) -> *mut PyObject { + if PyInstance_Check(x) != 0 { + (*(x as *mut PyInstanceObject)).in_class as *mut PyObject + } else { + (*x).ob_type as *mut PyObject + } +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyExc_BaseException: *mut PyObject; + pub static mut PyExc_Exception: *mut PyObject; + pub static mut PyExc_StopIteration: *mut PyObject; + pub static mut PyExc_GeneratorExit: *mut PyObject; + pub static mut PyExc_StandardError: *mut PyObject; + pub static mut PyExc_ArithmeticError: *mut PyObject; + pub static mut PyExc_LookupError: *mut PyObject; + pub static mut PyExc_AssertionError: *mut PyObject; + pub static mut PyExc_AttributeError: *mut PyObject; + pub static mut PyExc_EOFError: *mut PyObject; + pub static mut PyExc_FloatingPointError: *mut PyObject; + pub static mut PyExc_EnvironmentError: *mut PyObject; + pub static mut PyExc_IOError: *mut PyObject; + pub static mut PyExc_OSError: *mut PyObject; + pub static mut PyExc_ImportError: *mut PyObject; + pub static mut PyExc_IndexError: *mut PyObject; + pub static mut PyExc_KeyError: *mut PyObject; + pub static mut PyExc_KeyboardInterrupt: *mut PyObject; + pub static mut PyExc_MemoryError: *mut PyObject; + pub static mut PyExc_NameError: *mut PyObject; + pub static mut PyExc_OverflowError: *mut PyObject; + pub static mut PyExc_RuntimeError: *mut PyObject; + pub static mut PyExc_NotImplementedError: *mut PyObject; + pub static mut PyExc_SyntaxError: *mut PyObject; + pub static mut PyExc_IndentationError: *mut PyObject; + pub static mut PyExc_TabError: *mut PyObject; + pub static mut PyExc_ReferenceError: *mut PyObject; + pub static mut PyExc_SystemError: *mut PyObject; + pub static mut PyExc_SystemExit: *mut PyObject; + pub static mut PyExc_TypeError: *mut PyObject; + pub static mut PyExc_UnboundLocalError: *mut PyObject; + pub static mut PyExc_UnicodeError: *mut PyObject; + pub static mut PyExc_UnicodeEncodeError: *mut PyObject; + pub static mut PyExc_UnicodeDecodeError: *mut PyObject; + pub static mut PyExc_UnicodeTranslateError: *mut PyObject; + pub static mut PyExc_ValueError: *mut PyObject; + pub static mut PyExc_ZeroDivisionError: *mut PyObject; + #[cfg(windows)] pub static mut PyExc_WindowsError: *mut PyObject; + pub static mut PyExc_BufferError: *mut PyObject; + pub static mut PyExc_MemoryErrorInst: *mut PyObject; + pub static mut PyExc_RecursionErrorInst: *mut PyObject; + pub static mut PyExc_Warning: *mut PyObject; + pub static mut PyExc_UserWarning: *mut PyObject; + pub static mut PyExc_DeprecationWarning: *mut PyObject; + pub static mut PyExc_PendingDeprecationWarning: *mut PyObject; + pub static mut PyExc_SyntaxWarning: *mut PyObject; + pub static mut PyExc_RuntimeWarning: *mut PyObject; + pub static mut PyExc_FutureWarning: *mut PyObject; + pub static mut PyExc_ImportWarning: *mut PyObject; + pub static mut PyExc_UnicodeWarning: *mut PyObject; + pub static mut PyExc_BytesWarning: *mut PyObject; + + pub fn PyErr_BadArgument() -> c_int; + pub fn PyErr_NoMemory() -> *mut PyObject; + pub fn PyErr_SetFromErrno(arg1: *mut PyObject) -> *mut PyObject; + pub fn PyErr_SetFromErrnoWithFilenameObject(arg1: *mut PyObject, + arg2: *mut PyObject) + -> *mut PyObject; + pub fn PyErr_SetFromErrnoWithFilename(arg1: *mut PyObject, + arg2: *const c_char) + -> *mut PyObject; + pub fn PyErr_Format(arg1: *mut PyObject, arg2: *const c_char, ...) + -> *mut PyObject; + pub fn PyErr_BadInternalCall(); + pub fn _PyErr_BadInternalCall(filename: *mut c_char, + lineno: c_int); + pub fn PyErr_NewException(name: *mut c_char, base: *mut PyObject, + dict: *mut PyObject) -> *mut PyObject; + pub fn PyErr_NewExceptionWithDoc(name: *mut c_char, + doc: *mut c_char, + base: *mut PyObject, dict: *mut PyObject) + -> *mut PyObject; + pub fn PyErr_WriteUnraisable(arg1: *mut PyObject); + pub fn PyErr_CheckSignals() -> c_int; + pub fn PyErr_SetInterrupt(); + pub fn PySignal_SetWakeupFd(fd: c_int) -> c_int; + pub fn PyErr_SyntaxLocation(arg1: *const c_char, + arg2: c_int); + pub fn PyErr_ProgramText(arg1: *const c_char, arg2: c_int) + -> *mut PyObject; +} + +#[cfg(py_sys_config="Py_USING_UNICODE")] +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyUnicodeDecodeError_Create(arg1: *const c_char, + arg2: *const c_char, + arg3: Py_ssize_t, arg4: Py_ssize_t, + arg5: Py_ssize_t, + arg6: *const c_char) + -> *mut PyObject; + pub fn PyUnicodeEncodeError_Create(arg1: *const c_char, + arg2: *const Py_UNICODE, + arg3: Py_ssize_t, arg4: Py_ssize_t, + arg5: Py_ssize_t, + arg6: *const c_char) + -> *mut PyObject; + pub fn PyUnicodeTranslateError_Create(arg1: *const Py_UNICODE, + arg2: Py_ssize_t, arg3: Py_ssize_t, + arg4: Py_ssize_t, + arg5: *const c_char) + -> *mut PyObject; + pub fn PyUnicodeEncodeError_GetEncoding(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeDecodeError_GetEncoding(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeEncodeError_GetObject(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeDecodeError_GetObject(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeTranslateError_GetObject(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeEncodeError_GetStart(arg1: *mut PyObject, + arg2: *mut Py_ssize_t) + -> c_int; + pub fn PyUnicodeDecodeError_GetStart(arg1: *mut PyObject, + arg2: *mut Py_ssize_t) + -> c_int; + pub fn PyUnicodeTranslateError_GetStart(arg1: *mut PyObject, + arg2: *mut Py_ssize_t) + -> c_int; + pub fn PyUnicodeEncodeError_SetStart(arg1: *mut PyObject, + arg2: Py_ssize_t) -> c_int; + pub fn PyUnicodeDecodeError_SetStart(arg1: *mut PyObject, + arg2: Py_ssize_t) -> c_int; + pub fn PyUnicodeTranslateError_SetStart(arg1: *mut PyObject, + arg2: Py_ssize_t) + -> c_int; + pub fn PyUnicodeEncodeError_GetEnd(arg1: *mut PyObject, + arg2: *mut Py_ssize_t) + -> c_int; + pub fn PyUnicodeDecodeError_GetEnd(arg1: *mut PyObject, + arg2: *mut Py_ssize_t) + -> c_int; + pub fn PyUnicodeTranslateError_GetEnd(arg1: *mut PyObject, + arg2: *mut Py_ssize_t) + -> c_int; + pub fn PyUnicodeEncodeError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) + -> c_int; + pub fn PyUnicodeDecodeError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) + -> c_int; + pub fn PyUnicodeTranslateError_SetEnd(arg1: *mut PyObject, + arg2: Py_ssize_t) -> c_int; + pub fn PyUnicodeEncodeError_GetReason(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeDecodeError_GetReason(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeTranslateError_GetReason(arg1: *mut PyObject) + -> *mut PyObject; + pub fn PyUnicodeEncodeError_SetReason(arg1: *mut PyObject, + arg2: *const c_char) + -> c_int; + pub fn PyUnicodeDecodeError_SetReason(arg1: *mut PyObject, + arg2: *const c_char) + -> c_int; + pub fn PyUnicodeTranslateError_SetReason(arg1: *mut PyObject, + arg2: *const c_char) + -> c_int; +} + diff --git a/src/ffi2/pymem.rs b/src/ffi2/pymem.rs new file mode 100644 index 00000000..66db582a --- /dev/null +++ b/src/ffi2/pymem.rs @@ -0,0 +1,7 @@ +use libc::{c_void, size_t}; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyMem_Malloc(n: size_t) -> *mut c_void; + pub fn PyMem_Realloc(p: *mut c_void, n: size_t) -> *mut c_void; + pub fn PyMem_Free(p: *mut c_void); +} diff --git a/src/ffi2/pyport.rs b/src/ffi2/pyport.rs new file mode 100644 index 00000000..cbfa8e6b --- /dev/null +++ b/src/ffi2/pyport.rs @@ -0,0 +1,9 @@ + +pub type Py_uintptr_t = ::libc::uintptr_t; +pub type Py_intptr_t = ::libc::intptr_t; +pub type Py_ssize_t = ::libc::ssize_t; +pub type Py_hash_t = Py_ssize_t; +pub type Py_uhash_t = ::libc::size_t; + +pub const PY_SSIZE_T_MIN : Py_ssize_t = ::std::isize::MIN as Py_ssize_t; +pub const PY_SSIZE_T_MAX : Py_ssize_t = ::std::isize::MAX as Py_ssize_t; diff --git a/src/ffi2/pystate.rs b/src/ffi2/pystate.rs new file mode 100644 index 00000000..7577ef81 --- /dev/null +++ b/src/ffi2/pystate.rs @@ -0,0 +1,106 @@ +use std::os::raw::{c_int, c_long}; +use ffi2::object::PyObject; +use ffi2::frameobject::PyFrameObject; + +pub enum PyInterpreterState { } + +pub type Py_tracefunc = + unsafe extern "C" fn (arg1: *mut PyObject, arg2: *mut PyFrameObject, + arg3: c_int, arg4: *mut PyObject) + -> c_int; + +/* The following values are used for 'what' for tracefunc functions: */ +pub const PyTrace_CALL : c_int = 0; +pub const PyTrace_EXCEPTION : c_int = 1; +pub const PyTrace_LINE : c_int = 2; +pub const PyTrace_RETURN : c_int = 3; +pub const PyTrace_C_CALL : c_int = 4; +pub const PyTrace_C_EXCEPTION : c_int = 5; +pub const PyTrace_C_RETURN : c_int = 6; + +#[repr(C)] +#[derive(Copy)] +pub struct PyThreadState { + pub next: *mut PyThreadState, + pub interp: *mut PyInterpreterState, + pub frame: *mut PyFrameObject, + pub recursion_depth: c_int, + pub tracing: c_int, + pub use_tracing: c_int, + pub c_profilefunc: Option, + pub c_tracefunc: Option, + pub c_profileobj: *mut PyObject, + pub c_traceobj: *mut PyObject, + pub curexc_type: *mut PyObject, + pub curexc_value: *mut PyObject, + pub curexc_traceback: *mut PyObject, + pub exc_type: *mut PyObject, + pub exc_value: *mut PyObject, + pub exc_traceback: *mut PyObject, + pub dict: *mut PyObject, + pub tick_counter: c_int, + pub gilstate_counter: c_int, + pub async_exc: *mut PyObject, + pub thread_id: c_long, + pub trash_delete_nesting: c_int, + pub trash_delete_later: *mut PyObject, +} + +impl Clone for PyThreadState { + #[inline] fn clone(&self) -> PyThreadState { *self } +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub enum PyGILState_STATE { + PyGILState_LOCKED, + PyGILState_UNLOCKED +} + + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + static mut _PyThreadState_Current: *mut PyThreadState; + //static mut _PyThreadState_GetFrame: PyThreadFrameGetter; + + pub fn PyInterpreterState_New() -> *mut PyInterpreterState; + pub fn PyInterpreterState_Clear(arg1: *mut PyInterpreterState); + pub fn PyInterpreterState_Delete(arg1: *mut PyInterpreterState); + pub fn PyThreadState_New(arg1: *mut PyInterpreterState) + -> *mut PyThreadState; + pub fn _PyThreadState_Prealloc(arg1: *mut PyInterpreterState) + -> *mut PyThreadState; + pub fn _PyThreadState_Init(arg1: *mut PyThreadState); + pub fn PyThreadState_Clear(arg1: *mut PyThreadState); + pub fn PyThreadState_Delete(arg1: *mut PyThreadState); + #[cfg(py_sys_config="WITH_THREAD")] + pub fn PyThreadState_DeleteCurrent(); + pub fn PyThreadState_Get() -> *mut PyThreadState; + pub fn PyThreadState_Swap(arg1: *mut PyThreadState) -> *mut PyThreadState; + pub fn PyThreadState_GetDict() -> *mut PyObject; + pub fn PyThreadState_SetAsyncExc(arg1: c_long, + arg2: *mut PyObject) -> c_int; + pub fn PyGILState_Ensure() -> PyGILState_STATE; + pub fn PyGILState_Release(arg1: PyGILState_STATE); + pub fn PyGILState_GetThisThreadState() -> *mut PyThreadState; + fn _PyThread_CurrentFrames() -> *mut PyObject; + pub fn PyInterpreterState_Head() -> *mut PyInterpreterState; + pub fn PyInterpreterState_Next(arg1: *mut PyInterpreterState) + -> *mut PyInterpreterState; + pub fn PyInterpreterState_ThreadHead(arg1: *mut PyInterpreterState) + -> *mut PyThreadState; + pub fn PyThreadState_Next(arg1: *mut PyThreadState) -> *mut PyThreadState; +} + +#[cfg(py_sys_config="Py_DEBUG")] +#[inline(always)] +pub unsafe fn PyThreadState_GET() -> *mut PyThreadState { + PyThreadState_Get() +} + +#[cfg(not(py_sys_config="Py_DEBUG"))] +#[inline(always)] +pub unsafe fn PyThreadState_GET() -> *mut PyThreadState { + _PyThreadState_Current +} + + diff --git a/src/ffi2/pythonrun.rs b/src/ffi2/pythonrun.rs new file mode 100644 index 00000000..e28b68ec --- /dev/null +++ b/src/ffi2/pythonrun.rs @@ -0,0 +1,121 @@ +use libc::{c_char, c_int, FILE}; +use ffi2::object::*; +use ffi2::code::*; +use ffi2::pystate::PyThreadState; +use ffi2::pyarena::PyArena; + +pub const PyCF_MASK : c_int = (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | + CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | + CO_FUTURE_UNICODE_LITERALS); +pub const PyCF_MASK_OBSOLETE : c_int = (CO_NESTED); +pub const PyCF_SOURCE_IS_UTF8 : c_int = 0x0100; +pub const PyCF_DONT_IMPLY_DEDENT : c_int = 0x0200; +pub const PyCF_ONLY_AST : c_int = 0x0400; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyCompilerFlags { + cf_flags : c_int +} + +#[allow(missing_copy_implementations)] +pub enum Struct__mod { } +#[allow(missing_copy_implementations)] +pub enum Struct__node { } +#[allow(missing_copy_implementations)] +pub enum Struct_symtable { } + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn Py_SetProgramName(arg1: *mut c_char); + pub fn Py_GetProgramName() -> *mut c_char; + pub fn Py_SetPythonHome(arg1: *mut c_char); + pub fn Py_GetPythonHome() -> *mut c_char; + pub fn Py_Initialize(); + pub fn Py_InitializeEx(arg1: c_int); + pub fn Py_Finalize(); + pub fn Py_IsInitialized() -> c_int; + pub fn Py_NewInterpreter() -> *mut PyThreadState; + pub fn Py_EndInterpreter(arg1: *mut PyThreadState); + pub fn PyRun_AnyFileFlags(arg1: *mut FILE, arg2: *const c_char, + arg3: *mut PyCompilerFlags) -> c_int; + pub fn PyRun_AnyFileExFlags(arg1: *mut FILE, arg2: *const c_char, + arg3: c_int, + arg4: *mut PyCompilerFlags) -> c_int; + pub fn PyRun_SimpleStringFlags(arg1: *const c_char, + arg2: *mut PyCompilerFlags) + -> c_int; + pub fn PyRun_SimpleFileExFlags(arg1: *mut FILE, + arg2: *const c_char, + arg3: c_int, + arg4: *mut PyCompilerFlags) + -> c_int; + pub fn PyRun_InteractiveOneFlags(arg1: *mut FILE, + arg2: *const c_char, + arg3: *mut PyCompilerFlags) + -> c_int; + pub fn PyRun_InteractiveLoopFlags(arg1: *mut FILE, + arg2: *const c_char, + arg3: *mut PyCompilerFlags) + -> c_int; + pub fn PyParser_ASTFromString(arg1: *const c_char, + arg2: *const c_char, + arg3: c_int, + flags: *mut PyCompilerFlags, + arg4: *mut PyArena) -> *mut Struct__mod; + pub fn PyParser_ASTFromFile(arg1: *mut FILE, arg2: *const c_char, + arg3: c_int, + arg4: *mut c_char, + arg5: *mut c_char, + arg6: *mut PyCompilerFlags, + arg7: *mut c_int, arg8: *mut PyArena) + -> *mut Struct__mod; + pub fn PyParser_SimpleParseStringFlags(arg1: *const c_char, + arg2: c_int, + arg3: c_int) + -> *mut Struct__node; + pub fn PyParser_SimpleParseFileFlags(arg1: *mut FILE, + arg2: *const c_char, + arg3: c_int, + arg4: c_int) + -> *mut Struct__node; + pub fn PyRun_StringFlags(arg1: *const c_char, arg2: c_int, + arg3: *mut PyObject, arg4: *mut PyObject, + arg5: *mut PyCompilerFlags) -> *mut PyObject; + pub fn PyRun_FileExFlags(arg1: *mut FILE, arg2: *const c_char, + arg3: c_int, arg4: *mut PyObject, + arg5: *mut PyObject, arg6: c_int, + arg7: *mut PyCompilerFlags) -> *mut PyObject; + pub fn Py_CompileStringFlags(arg1: *const c_char, + arg2: *const c_char, + arg3: c_int, + arg4: *mut PyCompilerFlags) -> *mut PyObject; + pub fn Py_SymtableString(arg1: *const c_char, + arg2: *const c_char, arg3: c_int) + -> *mut Struct_symtable; + pub fn PyErr_Print(); + pub fn PyErr_PrintEx(arg1: c_int); + pub fn PyErr_Display(arg1: *mut PyObject, arg2: *mut PyObject, + arg3: *mut PyObject); + pub fn Py_AtExit(func: Option) + -> c_int; + pub fn Py_Exit(arg1: c_int); + pub fn Py_FdIsInteractive(arg1: *mut FILE, arg2: *const c_char) + -> c_int; + pub fn Py_Main(argc: c_int, argv: *mut *mut c_char) + -> c_int; + pub fn Py_GetProgramFullPath() -> *mut c_char; + pub fn Py_GetPrefix() -> *mut c_char; + pub fn Py_GetExecPrefix() -> *mut c_char; + pub fn Py_GetPath() -> *mut c_char; + pub fn Py_GetVersion() -> *const c_char; + pub fn Py_GetPlatform() -> *const c_char; + pub fn Py_GetCopyright() -> *const c_char; + pub fn Py_GetCompiler() -> *const c_char; + pub fn Py_GetBuildInfo() -> *const c_char; + fn _Py_svnversion() -> *const c_char; + pub fn Py_SubversionRevision() -> *const c_char; + pub fn Py_SubversionShortBranch() -> *const c_char; + fn _Py_hgidentifier() -> *const c_char; + fn _Py_hgversion() -> *const c_char; +} + diff --git a/src/ffi2/rangeobject.rs b/src/ffi2/rangeobject.rs new file mode 100644 index 00000000..62996656 --- /dev/null +++ b/src/ffi2/rangeobject.rs @@ -0,0 +1,13 @@ +use std::os::raw::c_int; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyRange_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyRange_Check(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyRange_Type; + (Py_TYPE(op) == u) as c_int +} + diff --git a/src/ffi2/setobject.rs b/src/ffi2/setobject.rs new file mode 100644 index 00000000..fbd2ece2 --- /dev/null +++ b/src/ffi2/setobject.rs @@ -0,0 +1,63 @@ +use std::os::raw::c_int; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +//enum PySetObject { /* representation hidden */ } + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PySet_Type: PyTypeObject; + pub static mut PyFrozenSet_Type: PyTypeObject; +} + +#[inline] +pub unsafe fn PyFrozenSet_CheckExact(ob : *mut PyObject) -> c_int { + let f : *mut PyTypeObject = &mut PyFrozenSet_Type; + (Py_TYPE(ob) == f) as c_int +} + +#[inline] +pub unsafe fn PyAnySet_CheckExact(ob : *mut PyObject) -> c_int { + let s : *mut PyTypeObject = &mut PySet_Type; + let f : *mut PyTypeObject = &mut PyFrozenSet_Type; + (Py_TYPE(ob) == s || Py_TYPE(ob) == f) as c_int +} + +#[inline] +pub unsafe fn PyAnySet_Check(ob : *mut PyObject) -> c_int { + (PyAnySet_CheckExact(ob) != 0 || + PyType_IsSubtype(Py_TYPE(ob), &mut PySet_Type) != 0 || + PyType_IsSubtype(Py_TYPE(ob), &mut PyFrozenSet_Type) != 0) as c_int +} + +#[inline] +pub unsafe fn PySet_Check(ob : *mut PyObject) -> c_int { + let s : *mut PyTypeObject = &mut PySet_Type; + (Py_TYPE(ob) == s || PyType_IsSubtype(Py_TYPE(ob), s) != 0) as c_int +} + +#[inline] +pub unsafe fn PyFrozenSet_Check(ob : *mut PyObject) -> c_int { + let f : *mut PyTypeObject = &mut PyFrozenSet_Type; + (Py_TYPE(ob) == f || PyType_IsSubtype(Py_TYPE(ob), f) != 0) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PySet_New(iterable: *mut PyObject) -> *mut PyObject; + pub fn PyFrozenSet_New(iterable: *mut PyObject) -> *mut PyObject; + pub fn PySet_Size(anyset: *mut PyObject) -> Py_ssize_t; + pub fn PySet_Clear(set: *mut PyObject) -> c_int; + pub fn PySet_Contains(anyset: *mut PyObject, key: *mut PyObject) + -> c_int; + pub fn PySet_Discard(set: *mut PyObject, key: *mut PyObject) + -> c_int; + pub fn PySet_Add(set: *mut PyObject, key: *mut PyObject) -> c_int; + //pub fn _PySet_Next(set: *mut PyObject, pos: *mut Py_ssize_t, + // key: *mut *mut PyObject) -> c_int; + //pub fn _PySet_NextEntry(set: *mut PyObject, pos: *mut Py_ssize_t, + // key: *mut *mut PyObject, + // hash: *mut c_long) -> c_int; + pub fn PySet_Pop(set: *mut PyObject) -> *mut PyObject; + //pub fn _PySet_Update(set: *mut PyObject, iterable: *mut PyObject) + // -> c_int; +} + diff --git a/src/ffi2/sliceobject.rs b/src/ffi2/sliceobject.rs new file mode 100644 index 00000000..c458fa51 --- /dev/null +++ b/src/ffi2/sliceobject.rs @@ -0,0 +1,50 @@ +use std::os::raw::c_int; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + static mut _Py_EllipsisObject: PyObject; +} + +#[inline(always)] +pub unsafe fn Py_Ellipsis() -> *mut PyObject { + &mut _Py_EllipsisObject +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PySliceObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub start: *mut PyObject, + pub stop: *mut PyObject, + pub step: *mut PyObject +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PySlice_Type: PyTypeObject; + pub static mut PyEllipsis_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PySlice_Check(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PySlice_Type) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PySlice_New(start: *mut PyObject, stop: *mut PyObject, + step: *mut PyObject) -> *mut PyObject; + pub fn PySlice_GetIndices(r: *mut PyObject, length: Py_ssize_t, + start: *mut Py_ssize_t, stop: *mut Py_ssize_t, + step: *mut Py_ssize_t) -> c_int; + pub fn PySlice_GetIndicesEx(r: *mut PyObject, length: Py_ssize_t, + start: *mut Py_ssize_t, stop: *mut Py_ssize_t, + step: *mut Py_ssize_t, + slicelength: *mut Py_ssize_t) + -> c_int; +} + diff --git a/src/ffi2/stringobject.rs b/src/ffi2/stringobject.rs new file mode 100644 index 00000000..195dbdfc --- /dev/null +++ b/src/ffi2/stringobject.rs @@ -0,0 +1,126 @@ +use std::os::raw::{c_char, c_int, c_long}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[allow(missing_copy_implementations)] +pub struct PyStringObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_size: Py_ssize_t, + pub ob_shash: c_long, + pub ob_sstate: c_int, + pub ob_sval: [c_char; 1], +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyBaseString_Type: PyTypeObject; + pub static mut PyString_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyString_Check(op : *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_STRING_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyString_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyString_Type; + (Py_TYPE(op) == u) as c_int +} + +#[inline(always)] +pub unsafe fn PyString_GET_SIZE(op : *mut PyObject) -> Py_ssize_t { + (*(op as *mut PyStringObject)).ob_size +} + +#[inline(always)] +pub unsafe fn PyString_AS_STRING(op : *mut PyObject) -> *mut c_char { + (*(op as *mut PyStringObject)).ob_sval.as_mut_ptr() +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyString_FromString(v: *const c_char) -> *mut PyObject; + pub fn PyString_FromStringAndSize(v: *const c_char, + len: Py_ssize_t) -> *mut PyObject; + pub fn PyString_FromFormat(format: *const c_char, ...) -> *mut PyObject; + pub fn PyString_Size(string: *mut PyObject) -> Py_ssize_t; + pub fn PyString_AsString(string: *mut PyObject) -> *mut c_char; + pub fn PyString_AsStringAndSize(obj: *mut PyObject, + s: *mut *mut c_char, + len: *mut Py_ssize_t) -> c_int; + pub fn PyString_Concat(string: *mut *mut PyObject, newpart: *mut PyObject); + pub fn PyString_ConcatAndDel(string: *mut *mut PyObject, newpart: *mut PyObject); + pub fn _PyString_Resize(string: *mut *mut PyObject, newsize: Py_ssize_t) -> c_int; + pub fn PyString_Format(format: *mut PyObject, args: *mut PyObject) + -> *mut PyObject; + pub fn PyString_InternInPlace(string: *mut *mut PyObject); + pub fn PyString_InternFromString(v: *const c_char) -> *mut PyObject; + pub fn PyString_Decode(s: *const c_char, size: Py_ssize_t, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + pub fn PyString_AsDecodedObject(str: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + pub fn PyString_Encode(s: *const c_char, size: Py_ssize_t, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + pub fn PyString_AsEncodedObject(str: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + + /* + pub fn PyString_Repr(arg1: *mut PyObject, arg2: c_int) + -> *mut PyObject; + pub fn _PyString_Eq(arg1: *mut PyObject, arg2: *mut PyObject) + -> c_int; + pub fn _PyString_FormatLong(arg1: *mut PyObject, arg2: c_int, + arg3: c_int, arg4: c_int, + arg5: *mut *mut c_char, + arg6: *mut c_int) -> *mut PyObject; + pub fn PyString_DecodeEscape(arg1: *const c_char, + arg2: Py_ssize_t, + arg3: *const c_char, + arg4: Py_ssize_t, + arg5: *const c_char) + -> *mut PyObject; + pub fn PyString_InternImmortal(arg1: *mut *mut PyObject); + pub fn _Py_ReleaseInternedStrings(); + pub fn _PyString_Join(sep: *mut PyObject, x: *mut PyObject) + -> *mut PyObject; + pub fn PyString_AsEncodedString(str: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) + -> *mut PyObject; + pub fn PyString_AsDecodedString(str: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) + -> *mut PyObject; + + pub fn _PyString_InsertThousandsGroupingLocale(buffer: + *mut c_char, + n_buffer: Py_ssize_t, + digits: + *mut c_char, + n_digits: Py_ssize_t, + min_width: Py_ssize_t) + -> Py_ssize_t; + pub fn _PyString_InsertThousandsGrouping(buffer: *mut c_char, + n_buffer: Py_ssize_t, + digits: *mut c_char, + n_digits: Py_ssize_t, + min_width: Py_ssize_t, + grouping: *const c_char, + thousands_sep: + *const c_char) + -> Py_ssize_t; + pub fn _PyBytes_FormatAdvanced(obj: *mut PyObject, + format_spec: *mut c_char, + format_spec_len: Py_ssize_t) + -> *mut PyObject;*/ +} + diff --git a/src/ffi2/structmember.rs b/src/ffi2/structmember.rs new file mode 100644 index 00000000..20097a01 --- /dev/null +++ b/src/ffi2/structmember.rs @@ -0,0 +1,60 @@ +use std::os::raw::{c_char, c_int}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::PyObject; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyMemberDef { + pub name: *mut c_char, + pub type_code: c_int, + pub offset: Py_ssize_t, + pub flags: c_int, + pub doc: *mut c_char +} + +/* Types */ +pub const T_SHORT : c_int = 0; +pub const T_INT : c_int = 1; +pub const T_LONG : c_int = 2; +pub const T_FLOAT : c_int = 3; +pub const T_DOUBLE : c_int = 4; +pub const T_STRING : c_int = 5; +pub const T_OBJECT : c_int = 6; +/* XXX the ordering here is weird for binary compatibility */ +pub const T_CHAR : c_int = 7; /* 1-character string */ +pub const T_BYTE : c_int = 8; /* 8-bit signed int */ +/* unsigned variants: */ +pub const T_UBYTE : c_int = 9; +pub const T_USHORT : c_int = 10; +pub const T_UINT : c_int = 11; +pub const T_ULONG : c_int = 12; + +/* Added by Jack: strings contained in the structure */ +pub const T_STRING_INPLACE : c_int = 13; + +/* Added by Lillo: bools contained in the structure (assumed char) */ +pub const T_BOOL : c_int = 14; + +pub const T_OBJECT_EX : c_int = 16; /* Like T_OBJECT, but raises AttributeError + when the value is NULL, instead of + converting to None. */ + +pub const T_LONGLONG : c_int = 17; +pub const T_ULONGLONG : c_int = 18; + +pub const T_PYSSIZET : c_int = 19; /* Py_ssize_t */ + + +/* Flags */ +pub const READONLY : c_int = 1; +pub const RO : c_int = READONLY; /* Shorthand */ +pub const READ_RESTRICTED : c_int = 2; +pub const PY_WRITE_RESTRICTED : c_int = 4; +pub const RESTRICTED : c_int = (READ_RESTRICTED | PY_WRITE_RESTRICTED); + + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyMember_GetOne(addr: *const c_char, l: *mut PyMemberDef) -> *mut PyObject; + pub fn PyMember_SetOne(addr: *mut c_char, l: *mut PyMemberDef, value: *mut PyObject) -> c_int; +} + diff --git a/src/ffi2/traceback.rs b/src/ffi2/traceback.rs new file mode 100644 index 00000000..71a96331 --- /dev/null +++ b/src/ffi2/traceback.rs @@ -0,0 +1,33 @@ +use std::os::raw::c_int; +use ffi2::object::*; +use ffi2::pyport::Py_ssize_t; +use ffi2::frameobject::PyFrameObject; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyTracebackObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub tb_next: *mut PyTracebackObject, + pub tb_frame: *mut PyFrameObject, + pub tb_lasti: c_int, + pub tb_lineno: c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyTraceBack_Here(arg1: *mut PyFrameObject) -> c_int; + pub fn PyTraceBack_Print(arg1: *mut PyObject, arg2: *mut PyObject) + -> c_int; + + pub static mut PyTraceBack_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyTraceBack_Check(op : *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyTraceBack_Type) as c_int +} + diff --git a/src/ffi2/tupleobject.rs b/src/ffi2/tupleobject.rs new file mode 100644 index 00000000..27758207 --- /dev/null +++ b/src/ffi2/tupleobject.rs @@ -0,0 +1,63 @@ +use std::os::raw::c_int; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyTupleObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub ob_size: Py_ssize_t, + pub ob_item: [*mut PyObject; 1], +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyTuple_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyTuple_Check(op : *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TUPLE_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyTuple_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyTuple_Type; + (Py_TYPE(op) == u) as c_int +} + + +// Macro, trading safety for speed +#[inline(always)] +pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { + *(*(op as *mut PyTupleObject)).ob_item.as_ptr().offset(i as isize) +} + +#[inline(always)] +pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { + Py_SIZE(op) +} + +/// Macro, *only* to be used to fill in brand new tuples +#[inline(always)] +pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { + *(*(op as *mut PyTupleObject)).ob_item.as_mut_ptr().offset(i as isize) = v; +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyTuple_New(size: Py_ssize_t) -> *mut PyObject; + pub fn PyTuple_Size(p: *mut PyObject) -> Py_ssize_t; + pub fn PyTuple_GetItem(p: *mut PyObject, pos: Py_ssize_t) -> *mut PyObject; + pub fn PyTuple_SetItem(p: *mut PyObject, pos: Py_ssize_t, + o: *mut PyObject) -> c_int; + pub fn PyTuple_GetSlice(p: *mut PyObject, low: Py_ssize_t, + high: Py_ssize_t) -> *mut PyObject; + pub fn _PyTuple_Resize(p: *mut *mut PyObject, newsize: Py_ssize_t) -> c_int; + pub fn PyTuple_Pack(n: Py_ssize_t, ...) -> *mut PyObject; + //pub fn _PyTuple_MaybeUntrack(arg1: *mut PyObject); + pub fn PyTuple_ClearFreeList() -> c_int; +} diff --git a/src/ffi2/unicodeobject.rs b/src/ffi2/unicodeobject.rs new file mode 100644 index 00000000..32503fcb --- /dev/null +++ b/src/ffi2/unicodeobject.rs @@ -0,0 +1,499 @@ +use libc::wchar_t; +use std::os::raw::{c_char, c_int, c_long, c_double}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[cfg(py_sys_config="Py_UNICODE_SIZE_4")] +pub const Py_UNICODE_SIZE : Py_ssize_t = 4; +#[cfg(not(py_sys_config="Py_UNICODE_SIZE_4"))] +pub const Py_UNICODE_SIZE : Py_ssize_t = 2; + +pub type Py_UCS4 = u32; + +#[cfg(py_sys_config="Py_UNICODE_SIZE_4")] +pub type Py_UNICODE = u32; +#[cfg(not(py_sys_config="Py_UNICODE_SIZE_4"))] +pub type Py_UNICODE = u16; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyUnicodeObject { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub length: Py_ssize_t, + pub data: *mut Py_UNICODE, + pub hash: c_long, + pub defenc: *mut PyObject, +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub static mut PyUnicode_Type: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyUnicode_Check(op : *mut PyObject) -> c_int { + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS) +} + +#[inline(always)] +pub unsafe fn PyUnicode_CheckExact(op : *mut PyObject) -> c_int { + let u : *mut PyTypeObject = &mut PyUnicode_Type; + (Py_TYPE(op) == u) as c_int +} + +#[inline(always)] +pub unsafe fn PyUnicode_GET_SIZE(o: *mut PyObject) -> Py_ssize_t { + (*(o as *mut PyUnicodeObject)).length +} + +#[inline(always)] +pub unsafe fn PyUnicode_GET_DATA_SIZE(o: *mut PyObject) -> Py_ssize_t { + (*(o as *mut PyUnicodeObject)).length * Py_UNICODE_SIZE +} + +#[inline(always)] +pub unsafe fn PyUnicode_AS_UNICODE(o: *mut PyObject) -> *mut Py_UNICODE { + (*(o as *mut PyUnicodeObject)).data +} + +#[inline(always)] +pub unsafe fn PyUnicode_AS_DATA(o: *mut PyObject) -> *const c_char { + (*(o as *mut PyUnicodeObject)).data as *const c_char +} + +pub const Py_UNICODE_REPLACEMENT_CHARACTER : Py_UNICODE = 0xFFFD; + + +#[allow(dead_code)] +#[cfg(py_sys_config="Py_UNICODE_SIZE_4")] +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + fn PyUnicodeUCS4_FromUnicode(u: *const Py_UNICODE, size: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_FromStringAndSize(u: *const c_char, + size: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_FromString(u: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsUnicode(unicode: *mut PyObject) -> *mut Py_UNICODE; + fn PyUnicodeUCS4_GetSize(unicode: *mut PyObject) -> Py_ssize_t; + fn PyUnicodeUCS4_GetMax() -> Py_UNICODE; + fn PyUnicodeUCS4_Resize(unicode: *mut *mut PyObject, + length: Py_ssize_t) -> c_int; + fn PyUnicodeUCS4_FromEncodedObject(obj: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_FromObject(obj: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_FromFormatV(arg1: *const c_char, ...) -> *mut PyObject; + fn PyUnicodeUCS4_FromFormat(arg1: *const c_char, ...) -> *mut PyObject; + fn _PyUnicode_FormatAdvanced(obj: *mut PyObject, + format_spec: *mut Py_UNICODE, + format_spec_len: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_FromWideChar(w: *const wchar_t, size: Py_ssize_t) + -> *mut PyObject; + fn PyUnicodeUCS4_AsWideChar(unicode: *mut PyUnicodeObject, + w: *mut wchar_t, size: Py_ssize_t) -> Py_ssize_t; + fn PyUnicodeUCS4_FromOrdinal(ordinal: c_int) -> *mut PyObject; + fn PyUnicodeUCS4_ClearFreelist() -> c_int; + fn _PyUnicodeUCS4_AsDefaultEncodedString(arg1: *mut PyObject, arg2: *const c_char) + -> *mut PyObject; + fn PyUnicodeUCS4_GetDefaultEncoding() -> *const c_char; + fn PyUnicodeUCS4_SetDefaultEncoding(encoding: *const c_char) -> c_int; + fn PyUnicodeUCS4_Decode(s: *const c_char, size: Py_ssize_t, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_Encode(s: *const Py_UNICODE, size: Py_ssize_t, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsEncodedObject(unicode: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsEncodedString(unicode: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicode_BuildEncodingMap(string: *mut PyObject) -> *mut PyObject; + fn PyUnicode_DecodeUTF7(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicode_DecodeUTF7Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + consumed: *mut Py_ssize_t) -> *mut PyObject; + fn PyUnicode_EncodeUTF7(data: *const Py_UNICODE, length: Py_ssize_t, + base64SetO: c_int, + base64WhiteSpace: c_int, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeUTF8(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeUTF8Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + consumed: *mut Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_AsUTF8String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeUTF8(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeUTF32(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeUTF32Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int, + consumed: *mut Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_AsUTF32String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeUTF32(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char, + byteorder: c_int) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeUTF16(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeUTF16Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int, + consumed: *mut Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_AsUTF16String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeUTF16(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char, + byteorder: c_int) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeUnicodeEscape(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeUnicodeEscape(data: *const Py_UNICODE, + length: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeRawUnicodeEscape(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsRawUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeRawUnicodeEscape(data: *const Py_UNICODE, + length: Py_ssize_t) -> *mut PyObject; + fn _PyUnicode_DecodeUnicodeInternal(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeLatin1(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsLatin1String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeLatin1(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeASCII(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsASCIIString(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeASCII(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_DecodeCharmap(string: *const c_char, + length: Py_ssize_t, + mapping: *mut PyObject, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_AsCharmapString(unicode: *mut PyObject, + mapping: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeCharmap(data: *const Py_UNICODE, + length: Py_ssize_t, + mapping: *mut PyObject, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_TranslateCharmap(data: *const Py_UNICODE, + length: Py_ssize_t, + table: *mut PyObject, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS4_EncodeDecimal(s: *mut Py_UNICODE, length: Py_ssize_t, + output: *mut c_char, + errors: *const c_char) -> c_int; + fn PyUnicodeUCS4_Concat(left: *mut PyObject, right: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_Split(s: *mut PyObject, sep: *mut PyObject, + maxsplit: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_Splitlines(s: *mut PyObject, keepends: c_int) -> *mut PyObject; + fn PyUnicodeUCS4_Partition(s: *mut PyObject, sep: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_RPartition(s: *mut PyObject, sep: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_RSplit(s: *mut PyObject, sep: *mut PyObject, + maxsplit: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_Translate(str: *mut PyObject, table: *mut PyObject, errors: *const c_char) + -> *mut PyObject; + fn PyUnicodeUCS4_Join(separator: *mut PyObject, seq: *mut PyObject) + -> *mut PyObject; + fn PyUnicodeUCS4_Tailmatch(str: *mut PyObject, substr: *mut PyObject, + start: Py_ssize_t, end: Py_ssize_t, + direction: c_int) -> Py_ssize_t; + fn PyUnicodeUCS4_Find(str: *mut PyObject, substr: *mut PyObject, + start: Py_ssize_t, end: Py_ssize_t, + direction: c_int) -> Py_ssize_t; + fn PyUnicodeUCS4_Count(str: *mut PyObject, substr: *mut PyObject, + start: Py_ssize_t, end: Py_ssize_t) -> Py_ssize_t; + fn PyUnicodeUCS4_Replace(str: *mut PyObject, substr: *mut PyObject, + replstr: *mut PyObject, maxcount: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS4_Compare(left: *mut PyObject, right: *mut PyObject) -> c_int; + fn PyUnicodeUCS4_RichCompare(left: *mut PyObject, + right: *mut PyObject, op: c_int) -> *mut PyObject; + fn PyUnicodeUCS4_Format(format: *mut PyObject, args: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS4_Contains(container: *mut PyObject, element: *mut PyObject) -> c_int; + fn _PyUnicode_XStrip(_self: *mut PyUnicodeObject, + striptype: c_int, sepobj: *mut PyObject) -> *mut PyObject; + fn _PyUnicodeUCS4_IsLowercase(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_IsUppercase(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_IsTitlecase(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_IsWhitespace(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_IsLinebreak(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_ToLowercase(ch: Py_UNICODE) -> Py_UNICODE; + fn _PyUnicodeUCS4_ToUppercase(ch: Py_UNICODE) -> Py_UNICODE; + fn _PyUnicodeUCS4_ToTitlecase(ch: Py_UNICODE) -> Py_UNICODE; + fn _PyUnicodeUCS4_ToDecimalDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_ToDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_ToNumeric(ch: Py_UNICODE) -> c_double; + fn _PyUnicodeUCS4_IsDecimalDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_IsDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_IsNumeric(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS4_IsAlpha(ch: Py_UNICODE) -> c_int; +} + +#[allow(dead_code)] +#[cfg(not(py_sys_config="Py_UNICODE_SIZE_4"))] +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + fn PyUnicodeUCS2_FromUnicode(u: *const Py_UNICODE, size: Py_ssize_t) + -> *mut PyObject; + fn PyUnicodeUCS2_FromStringAndSize(u: *const c_char, + size: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS2_FromString(u: *const c_char) + -> *mut PyObject; + fn PyUnicodeUCS2_AsUnicode(unicode: *mut PyObject) -> *mut Py_UNICODE; + fn PyUnicodeUCS2_GetSize(unicode: *mut PyObject) -> Py_ssize_t; + fn PyUnicodeUCS2_GetMax() -> Py_UNICODE; + fn PyUnicodeUCS2_Resize(unicode: *mut *mut PyObject, + length: Py_ssize_t) -> c_int; + fn PyUnicodeUCS2_FromEncodedObject(obj: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_FromObject(obj: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_FromFormatV(arg1: *const c_char, ...) -> *mut PyObject; + fn PyUnicodeUCS2_FromFormat(arg1: *const c_char, ...) -> *mut PyObject; + fn _PyUnicode_FormatAdvanced(obj: *mut PyObject, + format_spec: *mut Py_UNICODE, + format_spec_len: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS2_FromWideChar(w: *const wchar_t, size: Py_ssize_t) + -> *mut PyObject; + fn PyUnicodeUCS2_AsWideChar(unicode: *mut PyUnicodeObject, + w: *mut wchar_t, size: Py_ssize_t) + -> Py_ssize_t; + fn PyUnicodeUCS2_FromOrdinal(ordinal: c_int) -> *mut PyObject; + fn PyUnicodeUCS2_ClearFreelist() -> c_int; + fn _PyUnicodeUCS2_AsDefaultEncodedString(arg1: *mut PyObject, + arg2: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_GetDefaultEncoding() -> *const c_char; + fn PyUnicodeUCS2_SetDefaultEncoding(encoding: *const c_char) -> c_int; + fn PyUnicodeUCS2_Decode(s: *const c_char, size: Py_ssize_t, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_Encode(s: *const Py_UNICODE, size: Py_ssize_t, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_AsEncodedObject(unicode: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_AsEncodedString(unicode: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject; + fn PyUnicode_BuildEncodingMap(string: *mut PyObject) -> *mut PyObject; + fn PyUnicode_DecodeUTF7(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicode_DecodeUTF7Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + consumed: *mut Py_ssize_t) -> *mut PyObject; + fn PyUnicode_EncodeUTF7(data: *const Py_UNICODE, length: Py_ssize_t, + base64SetO: c_int, + base64WhiteSpace: c_int, + errors: *const c_char) + -> *mut PyObject; + fn PyUnicodeUCS2_DecodeUTF8(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) + -> *mut PyObject; + fn PyUnicodeUCS2_DecodeUTF8Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + consumed: *mut Py_ssize_t) + -> *mut PyObject; + fn PyUnicodeUCS2_AsUTF8String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeUTF8(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeUTF32(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeUTF32Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int, + consumed: *mut Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS2_AsUTF32String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeUTF32(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char, + byteorder: c_int) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeUTF16(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeUTF16Stateful(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char, + byteorder: *mut c_int, + consumed: *mut Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS2_AsUTF16String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeUTF16(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char, + byteorder: c_int) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeUnicodeEscape(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_AsUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeUnicodeEscape(data: *const Py_UNICODE, + length: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeRawUnicodeEscape(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_AsRawUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeRawUnicodeEscape(data: *const Py_UNICODE, + length: Py_ssize_t) -> *mut PyObject; + fn _PyUnicode_DecodeUnicodeInternal(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeLatin1(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_AsLatin1String(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeLatin1(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeASCII(string: *const c_char, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_AsASCIIString(unicode: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeASCII(data: *const Py_UNICODE, + length: Py_ssize_t, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_DecodeCharmap(string: *const c_char, + length: Py_ssize_t, + mapping: *mut PyObject, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_AsCharmapString(unicode: *mut PyObject, + mapping: *mut PyObject) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeCharmap(data: *const Py_UNICODE, + length: Py_ssize_t, + mapping: *mut PyObject, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_TranslateCharmap(data: *const Py_UNICODE, + length: Py_ssize_t, + table: *mut PyObject, + errors: *const c_char) -> *mut PyObject; + fn PyUnicodeUCS2_EncodeDecimal(s: *mut Py_UNICODE, length: Py_ssize_t, + output: *mut c_char, + errors: *const c_char) -> c_int; + fn PyUnicodeUCS2_Concat(left: *mut PyObject, right: *mut PyObject) + -> *mut PyObject; + fn PyUnicodeUCS2_Split(s: *mut PyObject, sep: *mut PyObject, + maxsplit: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS2_Splitlines(s: *mut PyObject, keepends: c_int) + -> *mut PyObject; + fn PyUnicodeUCS2_Partition(s: *mut PyObject, sep: *mut PyObject) + -> *mut PyObject; + fn PyUnicodeUCS2_RPartition(s: *mut PyObject, sep: *mut PyObject) + -> *mut PyObject; + fn PyUnicodeUCS2_RSplit(s: *mut PyObject, sep: *mut PyObject, + maxsplit: Py_ssize_t) -> *mut PyObject; + fn PyUnicodeUCS2_Translate(str: *mut PyObject, table: *mut PyObject, + errors: *const c_char) + -> *mut PyObject; + fn PyUnicodeUCS2_Join(separator: *mut PyObject, seq: *mut PyObject) + -> *mut PyObject; + fn PyUnicodeUCS2_Tailmatch(str: *mut PyObject, substr: *mut PyObject, + start: Py_ssize_t, end: Py_ssize_t, + direction: c_int) -> Py_ssize_t; + fn PyUnicodeUCS2_Find(str: *mut PyObject, substr: *mut PyObject, + start: Py_ssize_t, end: Py_ssize_t, + direction: c_int) -> Py_ssize_t; + fn PyUnicodeUCS2_Count(str: *mut PyObject, substr: *mut PyObject, + start: Py_ssize_t, end: Py_ssize_t) + -> Py_ssize_t; + fn PyUnicodeUCS2_Replace(str: *mut PyObject, substr: *mut PyObject, + replstr: *mut PyObject, maxcount: Py_ssize_t) + -> *mut PyObject; + fn PyUnicodeUCS2_Compare(left: *mut PyObject, right: *mut PyObject) + -> c_int; + fn PyUnicodeUCS2_RichCompare(left: *mut PyObject, + right: *mut PyObject, op: c_int) + -> *mut PyObject; + fn PyUnicodeUCS2_Format(format: *mut PyObject, args: *mut PyObject) + -> *mut PyObject; + fn PyUnicodeUCS2_Contains(container: *mut PyObject, + element: *mut PyObject) -> c_int; + fn _PyUnicode_XStrip(_self: *mut PyUnicodeObject, + striptype: c_int, sepobj: *mut PyObject) + -> *mut PyObject; + fn _PyUnicodeUCS2_IsLowercase(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_IsUppercase(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_IsTitlecase(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_IsWhitespace(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_IsLinebreak(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_ToLowercase(ch: Py_UNICODE) -> Py_UNICODE; + fn _PyUnicodeUCS2_ToUppercase(ch: Py_UNICODE) -> Py_UNICODE; + fn _PyUnicodeUCS2_ToTitlecase(ch: Py_UNICODE) -> Py_UNICODE; + fn _PyUnicodeUCS2_ToDecimalDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_ToDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_ToNumeric(ch: Py_UNICODE) -> c_double; + fn _PyUnicodeUCS2_IsDecimalDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_IsDigit(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_IsNumeric(ch: Py_UNICODE) -> c_int; + fn _PyUnicodeUCS2_IsAlpha(ch: Py_UNICODE) -> c_int; +} + +#[inline(always)] +#[cfg(py_sys_config="Py_UNICODE_SIZE_4")] +pub unsafe fn PyUnicode_FromStringAndSize(u: *const c_char, size: Py_ssize_t) -> *mut PyObject { + PyUnicodeUCS4_FromStringAndSize(u, size) +} + +#[inline(always)] +#[cfg(not(py_sys_config="Py_UNICODE_SIZE_4"))] +pub unsafe fn PyUnicode_FromStringAndSize(u: *const c_char, size: Py_ssize_t) -> *mut PyObject { + PyUnicodeUCS2_FromStringAndSize(u, size) +} + +#[inline(always)] +#[cfg(py_sys_config="Py_UNICODE_SIZE_4")] +pub unsafe fn PyUnicode_AsUTF8String(u: *mut PyObject) -> *mut PyObject { + PyUnicodeUCS4_AsUTF8String(u) +} + +#[inline(always)] +#[cfg(not(py_sys_config="Py_UNICODE_SIZE_4"))] +pub unsafe fn PyUnicode_AsUTF8String(u: *mut PyObject) -> *mut PyObject { + PyUnicodeUCS2_AsUTF8String(u) +} + +#[inline(always)] +#[cfg(py_sys_config="Py_UNICODE_SIZE_4")] +pub unsafe fn PyUnicode_FromEncodedObject(obj: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject { + PyUnicodeUCS4_FromEncodedObject(obj, encoding, errors) +} + +#[inline(always)] +#[cfg(not(py_sys_config="Py_UNICODE_SIZE_4"))] +pub unsafe fn PyUnicode_FromEncodedObject(obj: *mut PyObject, + encoding: *const c_char, + errors: *const c_char) -> *mut PyObject { + PyUnicodeUCS2_FromEncodedObject(obj, encoding, errors) +} diff --git a/src/ffi2/warnings.rs b/src/ffi2/warnings.rs new file mode 100644 index 00000000..a609b0e8 --- /dev/null +++ b/src/ffi2/warnings.rs @@ -0,0 +1,19 @@ +use std::os::raw::{c_char, c_int}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::PyObject; + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyErr_WarnEx(category: *mut PyObject, msg: *const c_char, + stacklevel: Py_ssize_t) -> c_int; + pub fn PyErr_WarnExplicit(arg1: *mut PyObject, + arg2: *const c_char, + arg3: *const c_char, + arg4: c_int, + arg5: *const c_char, + arg6: *mut PyObject) -> c_int; +} + +#[inline] +pub unsafe fn PyErr_Warn(category: *mut PyObject, msg: *const c_char) -> c_int { + PyErr_WarnEx(category, msg, 1) +} diff --git a/src/ffi2/weakrefobject.rs b/src/ffi2/weakrefobject.rs new file mode 100644 index 00000000..f13714d0 --- /dev/null +++ b/src/ffi2/weakrefobject.rs @@ -0,0 +1,64 @@ +use std::os::raw::{c_int, c_long}; +use ffi2::pyport::Py_ssize_t; +use ffi2::object::*; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PyWeakReference { + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_next: *mut PyObject, + #[cfg(py_sys_config="Py_TRACE_REFS")] + pub _ob_prev: *mut PyObject, + pub ob_refcnt: Py_ssize_t, + pub ob_type: *mut PyTypeObject, + pub wr_object: *mut PyObject, + pub wr_callback: *mut PyObject, + pub hash: c_long, + pub wr_prev: *mut PyWeakReference, + pub wr_next: *mut PyWeakReference +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + static mut _PyWeakref_RefType: PyTypeObject; + static mut _PyWeakref_ProxyType: PyTypeObject; + static mut _PyWeakref_CallableProxyType: PyTypeObject; +} + +#[inline(always)] +pub unsafe fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int { + PyObject_TypeCheck(op, &mut _PyWeakref_RefType) +} + +#[inline(always)] +pub unsafe fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut _PyWeakref_RefType) as c_int +} + +#[inline(always)] +pub unsafe fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int { + ((Py_TYPE(op) == &mut _PyWeakref_ProxyType) || + (Py_TYPE(op) == &mut _PyWeakref_CallableProxyType)) as c_int +} + +#[inline(always)] +pub unsafe fn PyWeakref_Check(op: *mut PyObject) -> c_int { + (PyWeakref_CheckRef(op) != 0 || PyWeakref_CheckProxy(op) != 0) as c_int +} + +#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { + pub fn PyWeakref_NewRef(ob: *mut PyObject, callback: *mut PyObject) + -> *mut PyObject; + pub fn PyWeakref_NewProxy(ob: *mut PyObject, callback: *mut PyObject) + -> *mut PyObject; + pub fn PyWeakref_GetObject(_ref: *mut PyObject) -> *mut PyObject; + + pub fn _PyWeakref_GetWeakrefCount(head: *mut PyWeakReference) -> Py_ssize_t; + pub fn _PyWeakref_ClearRef(slf: *mut PyWeakReference); +} + +#[inline(always)] +pub unsafe fn PyWeakref_GET_OBJECT(_ref: *mut PyObject) -> *mut PyObject { + let obj = (*(_ref as *mut PyWeakReference)).wr_object; + if Py_REFCNT(obj) > 0 { obj } else { Py_None() } +} + diff --git a/src/function.rs b/src/function.rs index 5e9c9f0b..6434f408 100644 --- a/src/function.rs +++ b/src/function.rs @@ -75,8 +75,7 @@ macro_rules! py_method_def { /// # Example /// ``` /// #[macro_use] extern crate pyo3; -/// use pyo3::{Python, PyResult, PyErr, PyDict}; -/// use pyo3::{exc}; +/// use pyo3::{exc, Python, PyResult, PyErr, PyDict}; /// /// fn multiply(py: Python, lhs: i32, rhs: i32) -> PyResult { /// match lhs.checked_mul(rhs) { diff --git a/src/lib.rs b/src/lib.rs index c8e68bec..b3a0f005 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,16 +52,79 @@ //! Ok(()) //! } //! ``` +//! +//! Expands to an `extern "C"` function that allows Python to load +//! the rust code as a Python extension module. +//! +//! Macro syntax: `#[py::modinit(name)]` +//! +//! 1. `name`: The module name as a Rust identifier +//! 2. Decorate init function `Fn(Python, &PyModule) -> PyResult<()>`. +//! This function will be called when the module is imported, and is responsible +//! for adding the module's members. +//! +//! # Example +//! ``` +//! #![feature(proc_macro)] +//! #![macro_use] extern crate pyo3; +//! use pyo3::{py, Python, PyResult, PyObject, PyModule}; +//! +//! #[py::modinit(hello)] +//! fn init_module(py: Python, m: &PyModule) { +//! m.add(py, "__doc__", "Module documentation string")?; +//! m.add(py, "run", py_fn!(py, run()))?; +//! Ok(()) +//! } +//! +//! fn run(py: Python) -> PyResult { +//! println!("Rust says: Hello Python!"); +//! Ok(py.None()) +//! } +//! # fn main() {} +//! ``` +//! +//! In your `Cargo.toml`, use the `extension-module` feature for the `pyo3` dependency: +//! ```cargo +//! [dependencies.pyo3] +//! version = "*" +//! features = ["extension-module"] +//! ``` +//! +//! The full example project can be found at: +//! https://github.com/PyO3/setuptools-rust/tree/master/example/extensions +//! +//! Rust will compile the code into a file named `libhello.so`, but we have to +//! rename the file in order to use it with Python: +//! +//! ```bash +//! cp ./target/debug/libhello.so ./hello.so +//! ``` +//! (Note: on Mac OS you will have to rename `libhello.dynlib` to `libhello.so`) +//! +//! The extension module can then be imported into Python: +//! +//! ```python1 +//! >>> import hello +//! >>> hello.run() +//! Rust says: Hello Python! +//! ``` extern crate libc; extern crate backtrace; +extern crate pyo3cls; #[macro_use] extern crate log; -#[allow(unused_imports)] -#[macro_use] -pub extern crate pyo3cls; - +#[cfg(Py_3)] pub mod ffi; + +#[cfg(not(Py_3))] +mod ffi2; + +#[cfg(not(Py_3))] +pub mod ffi { + pub use ffi2::*; +} + pub use ffi::{Py_ssize_t, Py_hash_t}; pub mod pointers; @@ -82,12 +145,14 @@ pub mod class; pub use class::*; pub use self::typeob::PyTypeObject; -#[allow(non_camel_case_types)] - -use std::{ptr, mem}; - pub mod py { pub use pyo3cls::*; + + #[cfg(Py_3)] + pub use pyo3cls::mod3init as modinit; + + #[cfg(not(Py_3))] + pub use pyo3cls::mod2init as modinit; } /// Constructs a `&'static CStr` literal. @@ -125,110 +190,3 @@ pub mod freelist; // re-export for simplicity pub use std::os::raw::*; - -/// Expands to an `extern "C"` function that allows Python to load -/// the rust code as a Python extension module. -/// -/// Macro syntax: `py_module_initializer!($name, $py2_init, $py3_init, |$py, $m| $body)` -/// -/// 1. `name`: The module name as a Rust identifier. -/// 2. `py3_init`: "PyInit_" + $name. Necessary because macros can't use `concat_idents!()`. -/// 4. A lambda of type `Fn(Python, &PyModule) -> PyResult<()>`. -/// This function will be called when the module is imported, and is responsible -/// for adding the module's members. -/// -/// # Example -/// ``` -/// #[macro_use] extern crate pyo3; -/// use pyo3::{Python, PyResult, PyObject}; -/// -/// py_module_init!(hello, PyInit_hello, |py, m| { -/// m.add(py, "__doc__", "Module documentation string")?; -/// m.add(py, "run", py_fn!(py, run()))?; -/// Ok(()) -/// }); -/// -/// fn run(py: Python) -> PyResult { -/// println!("Rust says: Hello Python!"); -/// Ok(py.None()) -/// } -/// # fn main() {} -/// ``` -/// -/// In your `Cargo.toml`, use the `extension-module` feature for the `pyo3` dependency: -/// ```cargo -/// [dependencies.pyo3] -/// version = "*" -/// features = ["extension-module"] -/// ``` -/// The full example project can be found at: -/// https://github.com/PyO3/setuptools-rust/tree/master/example/extensions -/// -/// Rust will compile the code into a file named `libhello.so`, but we have to -/// rename the file in order to use it with Python: -/// -/// ```bash -/// cp ./target/debug/libhello.so ./hello.so -/// ``` -/// (Note: on Mac OS you will have to rename `libhello.dynlib` to `libhello.so`) -/// -/// The extension module can then be imported into Python: -/// -/// ```python -/// >>> import hello -/// >>> hello.run() -/// Rust says: Hello Python! -/// ``` -/// -#[macro_export] -macro_rules! py_module_init { - ($name: ident, $py3: ident, |$py_id: ident, $m_id: ident| $body: expr) => { - #[no_mangle] - #[allow(non_snake_case)] - pub unsafe extern "C" fn $py3() -> *mut $crate::ffi::PyObject { - // Nest init function so that $body isn't in unsafe context - fn init($py_id: $crate::Python, $m_id: &$crate::PyModule) -> $crate::PyResult<()> { - $body - } - static mut MODULE_DEF: $crate::ffi::PyModuleDef = $crate::ffi::PyModuleDef_INIT; - // We can't convert &'static str to *const c_char within a static initializer, - // so we'll do it here in the module initialization: - MODULE_DEF.m_name = concat!(stringify!($name), "\0").as_ptr() as *const _; - $crate::py_module_init_impl(&mut MODULE_DEF, init) - } - } -} - - -#[doc(hidden)] -pub unsafe fn py_module_init_impl( - def: *mut ffi::PyModuleDef, - init: fn(Python, &PyModule) -> PyResult<()>) -> *mut ffi::PyObject -{ - let guard = callback::AbortOnDrop("py_module_init"); - let py = Python::assume_gil_acquired(); - ffi::PyEval_InitThreads(); - let module = ffi::PyModule_Create(def); - if module.is_null() { - mem::forget(guard); - return module; - } - - let module = match PyObject::from_owned_ptr(py, module).cast_into::(py) { - Ok(m) => m, - Err(e) => { - PyErr::from(e).restore(py); - mem::forget(guard); - return ptr::null_mut(); - } - }; - let ret = match init(py, &module) { - Ok(()) => module.into_ptr(), - Err(e) => { - e.restore(py); - ptr::null_mut() - } - }; - mem::forget(guard); - ret -} diff --git a/src/objectprotocol.rs b/src/objectprotocol.rs index 44d44ce7..a06963f8 100644 --- a/src/objectprotocol.rs +++ b/src/objectprotocol.rs @@ -296,7 +296,7 @@ impl ObjectProtocol for T where T: ToPyPointer { /// Retrieves the hash code of the object. /// This is equivalent to the Python expression: 'hash(self)' #[inline] - fn hash(&self, py: Python) -> PyResult<::Py_hash_t> { + fn hash(&self, py: Python) -> PyResult { let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) }; if v == -1 { Err(PyErr::fetch(py)) diff --git a/src/objects/exc.rs b/src/objects/exc.rs index 076b66a7..3a9f0434 100644 --- a/src/objects/exc.rs +++ b/src/objects/exc.rs @@ -36,6 +36,7 @@ exc_type!(Exception, PyExc_Exception); exc_type!(LookupError, PyExc_LookupError); exc_type!(AssertionError, PyExc_AssertionError); exc_type!(AttributeError, PyExc_AttributeError); +exc_type!(BufferError, PyExc_BufferError); exc_type!(EOFError, PyExc_EOFError); exc_type!(EnvironmentError, PyExc_EnvironmentError); exc_type!(FloatingPointError, PyExc_FloatingPointError); @@ -61,21 +62,35 @@ exc_type!(ValueError, PyExc_ValueError); exc_type!(WindowsError, PyExc_WindowsError); exc_type!(ZeroDivisionError, PyExc_ZeroDivisionError); -exc_type!(BufferError, PyExc_BufferError); +#[cfg(Py_3)] exc_type!(BlockingIOError, PyExc_BlockingIOError); +#[cfg(Py_3)] exc_type!(BrokenPipeError, PyExc_BrokenPipeError); +#[cfg(Py_3)] exc_type!(ChildProcessError, PyExc_ChildProcessError); +#[cfg(Py_3)] exc_type!(ConnectionError, PyExc_ConnectionError); +#[cfg(Py_3)] exc_type!(ConnectionAbortedError, PyExc_ConnectionAbortedError); +#[cfg(Py_3)] exc_type!(ConnectionRefusedError, PyExc_ConnectionRefusedError); +#[cfg(Py_3)] exc_type!(ConnectionResetError, PyExc_ConnectionResetError); +#[cfg(Py_3)] exc_type!(FileExistsError, PyExc_FileExistsError); +#[cfg(Py_3)] exc_type!(FileNotFoundError, PyExc_FileNotFoundError); +#[cfg(Py_3)] exc_type!(InterruptedError, PyExc_InterruptedError); +#[cfg(Py_3)] exc_type!(IsADirectoryError, PyExc_IsADirectoryError); +#[cfg(Py_3)] exc_type!(NotADirectoryError, PyExc_NotADirectoryError); +#[cfg(Py_3)] exc_type!(PermissionError, PyExc_PermissionError); +#[cfg(Py_3)] exc_type!(ProcessLookupError, PyExc_ProcessLookupError); +#[cfg(Py_3)] exc_type!(TimeoutError, PyExc_TimeoutError); exc_type!(UnicodeDecodeError, PyExc_UnicodeDecodeError); diff --git a/src/objects/mod.rs b/src/objects/mod.rs index d4a8c9f9..16660adb 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -3,7 +3,6 @@ pub use self::object::PyObject; pub use self::typeobject::PyType; pub use self::module::PyModule; -pub use self::string::{PyBytes, PyString, PyStringData}; pub use self::iterator::PyIterator; pub use self::boolobject::PyBool; pub use self::bytearray::{PyByteArray}; @@ -14,6 +13,13 @@ pub use self::num::{PyLong, PyFloat}; pub use self::sequence::PySequence; pub use self::slice::PySlice; pub use self::set::{PySet, PyFrozenSet}; +pub use self::stringdata::PyStringData; + +#[cfg(Py_3)] +pub use self::string::{PyBytes, PyString}; + +#[cfg(not(Py_3))] +pub use self::string2::{PyBytes, PyString}; #[macro_export] @@ -272,7 +278,6 @@ macro_rules! pyobject_extract( mod typeobject; mod module; -mod string; mod dict; mod iterator; mod boolobject; @@ -282,6 +287,14 @@ mod list; mod num; mod sequence; mod slice; +mod stringdata; +mod stringutils; mod set; mod object; pub mod exc; + +#[cfg(Py_3)] +mod string; + +#[cfg(not(Py_3))] +mod string2; diff --git a/src/objects/string.rs b/src/objects/string.rs index 09fe0485..519a13c8 100644 --- a/src/objects/string.rs +++ b/src/objects/string.rs @@ -3,17 +3,15 @@ // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython use std; -use std::{mem, str, char}; -use std::ascii::AsciiExt; +use std::{mem, str}; use std::borrow::Cow; use std::os::raw::c_char; use ffi; use pointers::PyPtr; use python::{ToPyPointer, Python}; -use super::{exc, PyObject}; use err::{PyResult, PyErr}; -use conversion::{ToPyObject, IntoPyObject, RefFromPyObject}; +use super::{PyObject, PyStringData}; /// Represents a Python string. pub struct PyString(PyPtr); @@ -27,114 +25,6 @@ pub struct PyBytes(PyPtr); pyobject_convert!(PyBytes); pyobject_nativetype!(PyBytes, PyBytes_Check, PyBytes_Type); - -/// Enum of possible Python string representations. -#[derive(Clone, Copy, Debug)] -pub enum PyStringData<'a> { - Latin1(&'a [u8]), - Utf8(&'a [u8]), - Utf16(&'a [u16]), - Utf32(&'a [u32]) -} - -impl <'a> From<&'a str> for PyStringData<'a> { - #[inline] - fn from(val: &'a str) -> PyStringData<'a> { - PyStringData::Utf8(val.as_bytes()) - } -} - -impl <'a> From<&'a [u16]> for PyStringData<'a> { - #[inline] - fn from(val: &'a [u16]) -> PyStringData<'a> { - PyStringData::Utf16(val) - } -} - -impl <'a> From<&'a [u32]> for PyStringData<'a> { - #[inline] - fn from(val: &'a [u32]) -> PyStringData<'a> { - PyStringData::Utf32(val) - } -} - -impl <'a> PyStringData<'a> { - /// Convert the Python string data to a Rust string. - /// - /// For UTF-8 and ASCII-only latin-1, returns a borrow into the original string data. - /// For Latin-1, UTF-16 and UTF-32, returns an owned string. - /// - /// Fails with UnicodeDecodeError if the string data isn't valid in its encoding. - pub fn to_string(self, py: Python) -> PyResult> { - match self { - PyStringData::Utf8(data) => { - match str::from_utf8(data) { - Ok(s) => Ok(Cow::Borrowed(s)), - Err(e) => Err(PyErr::from_instance(py, try!(exc::UnicodeDecodeError::new_utf8(py, data, e)))) - } - } - PyStringData::Latin1(data) => { - if data.iter().all(|&b| b.is_ascii()) { - Ok(Cow::Borrowed(unsafe { str::from_utf8_unchecked(data) })) - } else { - Ok(Cow::Owned(data.iter().map(|&b| b as char).collect())) - } - }, - PyStringData::Utf16(data) => { - fn utf16_bytes(input: &[u16]) -> &[u8] { - unsafe { mem::transmute(input) } - } - match String::from_utf16(data) { - Ok(s) => Ok(Cow::Owned(s)), - Err(_) => Err(PyErr::from_instance(py, - try!(exc::UnicodeDecodeError::new(py, cstr!("utf-16"), - utf16_bytes(data), 0 .. 2*data.len(), cstr!("invalid utf-16"))) - )) - } - }, - PyStringData::Utf32(data) => { - fn utf32_bytes(input: &[u32]) -> &[u8] { - unsafe { mem::transmute(input) } - } - match data.iter().map(|&u| char::from_u32(u)).collect() { - Some(s) => Ok(Cow::Owned(s)), - None => Err(PyErr::from_instance(py, - try!(exc::UnicodeDecodeError::new(py, cstr!("utf-32"), - utf32_bytes(data), 0 .. 4*data.len(), cstr!("invalid utf-32"))) - )) - } - } - } - } - - /// Convert the Python string data to a Rust string. - /// - /// Returns a borrow into the original string data if possible. - /// - /// Data that isn't valid in its encoding will be replaced - /// with U+FFFD REPLACEMENT CHARACTER. - pub fn to_string_lossy(self) -> Cow<'a, str> { - match self { - PyStringData::Utf8(data) => String::from_utf8_lossy(data), - PyStringData::Latin1(data) => { - if data.iter().all(|&b| b.is_ascii()) { - Cow::Borrowed(unsafe { str::from_utf8_unchecked(data) }) - } else { - Cow::Owned(data.iter().map(|&b| b as char).collect()) - } - }, - PyStringData::Utf16(data) => { - Cow::Owned(String::from_utf16_lossy(data)) - }, - PyStringData::Utf32(data) => { - Cow::Owned(data.iter() - .map(|&u| char::from_u32(u).unwrap_or('\u{FFFD}')) - .collect()) - } - } - } -} - impl PyString { /// Creates a new Python string object. @@ -217,69 +107,6 @@ impl PyBytes { } } -/// Converts Rust `str` to Python object. -/// See `PyString::new` for details on the conversion. -impl ToPyObject for str { - #[inline] - fn to_object(&self, py: Python) -> PyObject { - PyString::new(py, self).into() - } -} -impl<'a> IntoPyObject for &'a str { - #[inline] - fn into_object(self, py: Python) -> PyObject { - PyString::new(py, self).into() - } -} - -/// Converts Rust `Cow` to Python object. -/// See `PyString::new` for details on the conversion. -impl<'a> ToPyObject for Cow<'a, str> { - #[inline] - fn to_object(&self, py: Python) -> PyObject { - PyString::new(py, self).into() - } -} - -/// Converts Rust `String` to Python object. -/// See `PyString::new` for details on the conversion. -impl ToPyObject for String { - #[inline] - fn to_object(&self, py: Python) -> PyObject { - PyString::new(py, self).into() - } -} -impl IntoPyObject for String { - #[inline] - fn into_object(self, py: Python) -> PyObject { - PyString::new(py, &self).into() - } -} - -// /// Allows extracting strings from Python objects. -// /// Accepts Python `str` and `unicode` objects. -pyobject_extract!(py, obj to Cow<'source, str> => { - try!(obj.cast_as::(py)).to_string(py) -}); - - -/// Allows extracting strings from Python objects. -/// Accepts Python `str` and `unicode` objects. -pyobject_extract!(py, obj to String => { - let s = try!(obj.cast_as::(py)); - s.to_string(py).map(Cow::into_owned) -}); - - -impl<'p> RefFromPyObject<'p> for str { - fn with_extracted(py: Python, obj: &'p PyObject, f: F) -> PyResult - where F: FnOnce(&str) -> R - { - let p = PyObject::from_borrowed_ptr(py, obj.as_ptr()); - let s = try!(p.extract::>(py)); - Ok(f(&s)) - } -} #[cfg(test)] mod test { diff --git a/src/objects/string2.rs b/src/objects/string2.rs new file mode 100644 index 00000000..364bdf60 --- /dev/null +++ b/src/objects/string2.rs @@ -0,0 +1,148 @@ +// Copyright (c) 2017-present PyO3 Project and Contributors +// +// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython + +use std; +use std::str; +use std::borrow::Cow; +use std::os::raw::c_char; + +use ffi; +use err::PyResult; +use pointers::PyPtr; +use python::{Python, ToPyPointer}; +use super::{PyObject, PyStringData}; + +/// Represents a Python string. Corresponds to `unicode` in Python 2 +pub struct PyString(PyPtr); + +pyobject_convert!(PyString); +pyobject_nativetype!(PyString, PyUnicode_Check, PyUnicode_Type); + +/// Represents a Python byte string. Corresponds to `str` in Python 2 +pub struct PyBytes(PyPtr); + +pyobject_convert!(PyBytes); +pyobject_nativetype!(PyBytes, PyString_Check, PyBaseString_Type); + + +impl PyBytes { + /// Creates a new Python byte string object. + /// The byte string is initialized by copying the data from the `&[u8]`. + /// + /// Panics if out of memory. + pub fn new(_py: Python, s: &[u8]) -> PyBytes { + let ptr = s.as_ptr() as *const c_char; + let len = s.len() as ffi::Py_ssize_t; + unsafe { + PyBytes(PyPtr::from_owned_ptr_or_panic( + ffi::PyBytes_FromStringAndSize(ptr, len))) + } + } + + /// Gets the Python string data as byte slice. + pub fn data(&self, _py: Python) -> &[u8] { + unsafe { + let buffer = ffi::PyBytes_AsString(self.as_ptr()) as *const u8; + let length = ffi::PyBytes_Size(self.as_ptr()) as usize; + std::slice::from_raw_parts(buffer, length) + } + } + + #[inline] + pub fn is_base_string(obj: &PyObject) -> bool { + unsafe { + ffi::PyType_FastSubclass( + ffi::Py_TYPE(obj.as_ptr()), + ffi::Py_TPFLAGS_STRING_SUBCLASS | ffi::Py_TPFLAGS_UNICODE_SUBCLASS) != 0 + } + } +} + +impl PyString { + /// Creates a new Python unicode string object. + /// + /// Panics if out of memory. + pub fn new(_py: Python, s: &str) -> PyString { + let ptr = s.as_ptr() as *const c_char; + let len = s.len() as ffi::Py_ssize_t; + unsafe { + PyString(PyPtr::from_owned_ptr_or_panic( + ffi::PyUnicode_FromStringAndSize(ptr, len))) + } + } + + pub fn from_object(py: Python, src: &PyObject, encoding: &str, errors: &str) + -> PyResult + { + unsafe { + Ok(PyString( + PyPtr::from_owned_ptr_or_err( + py, ffi::PyUnicode_FromEncodedObject( + src.as_ptr(), + encoding.as_ptr() as *const i8, + errors.as_ptr() as *const i8))?)) + } + } + + /// Converts from `PyString` to `PyBytes`. + #[inline] + pub fn into_bytes(self) -> PyBytes { + ::unchecked_downcast_into(self) + } + + /// Gets the python string data in its underlying representation. + pub fn data(&self, _py: Python) -> PyStringData { + unsafe { + let buffer = ffi::PyUnicode_AS_UNICODE(self.as_ptr()); + let length = ffi::PyUnicode_GET_SIZE(self.as_ptr()) as usize; + std::slice::from_raw_parts(buffer, length).into() + } + } + + /// Convert the `PyString` into a Rust string. + /// + /// Returns a `UnicodeDecodeError` if the input is not valid unicode + /// (containing unpaired surrogates). + pub fn to_string(&self, py: Python) -> PyResult> { + self.data(py).to_string(py) + } + + /// Convert the `PyString` into a Rust string. + /// + /// Unpaired surrogates are replaced with U+FFFD REPLACEMENT CHARACTER. + pub fn to_string_lossy(&self, py: Python) -> Cow { + self.data(py).to_string_lossy() + } +} + +#[cfg(test)] +mod test { + use python::Python; + use conversion::{ToPyObject, RefFromPyObject}; + + #[test] + fn test_non_bmp() { + let gil = Python::acquire_gil(); + let py = gil.python(); + let s = "\u{1F30F}"; + let py_string = s.to_object(py); + assert_eq!(s, py_string.extract::(py).unwrap()); + } + + #[test] + fn test_extract_str() { + let gil = Python::acquire_gil(); + let py = gil.python(); + let s = "Hello Python"; + let py_string = s.to_object(py); + let mut called = false; + RefFromPyObject::with_extracted(py, &py_string, + |s2: &str| { + assert_eq!(s, s2); + called = true; + }).unwrap(); + assert!(called); + } +} + diff --git a/src/objects/stringdata.rs b/src/objects/stringdata.rs new file mode 100644 index 00000000..07bfc85f --- /dev/null +++ b/src/objects/stringdata.rs @@ -0,0 +1,120 @@ +// Copyright (c) 2017-present PyO3 Project and Contributors +// +// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython + +use std::{mem, str, char}; +use std::ascii::AsciiExt; +use std::borrow::Cow; + +use python::Python; +use err::{PyErr, PyResult}; +use objects::exc; + +/// Enum of possible Python string representations. +#[derive(Clone, Copy, Debug)] +pub enum PyStringData<'a> { + Latin1(&'a [u8]), + Utf8(&'a [u8]), + Utf16(&'a [u16]), + Utf32(&'a [u32]) +} + +impl <'a> From<&'a str> for PyStringData<'a> { + #[inline] + fn from(val: &'a str) -> PyStringData<'a> { + PyStringData::Utf8(val.as_bytes()) +} +} + +impl <'a> From<&'a [u16]> for PyStringData<'a> { + #[inline] + fn from(val: &'a [u16]) -> PyStringData<'a> { + PyStringData::Utf16(val) + } +} + +impl <'a> From<&'a [u32]> for PyStringData<'a> { + #[inline] + fn from(val: &'a [u32]) -> PyStringData<'a> { + PyStringData::Utf32(val) + } +} + +impl <'a> PyStringData<'a> { + /// Convert the Python string data to a Rust string. + /// + /// For UTF-8 and ASCII-only latin-1, returns a borrow into the original string data. + /// For Latin-1, UTF-16 and UTF-32, returns an owned string. + /// + /// Fails with UnicodeDecodeError if the string data isn't valid in its encoding. + pub fn to_string(self, py: Python) -> PyResult> { + match self { + PyStringData::Utf8(data) => { + match str::from_utf8(data) { + Ok(s) => Ok(Cow::Borrowed(s)), + Err(e) => Err(PyErr::from_instance(py, try!(exc::UnicodeDecodeError::new_utf8(py, data, e)))) + } + } + PyStringData::Latin1(data) => { + if data.iter().all(|&b| b.is_ascii()) { + Ok(Cow::Borrowed(unsafe { str::from_utf8_unchecked(data) })) + } else { + Ok(Cow::Owned(data.iter().map(|&b| b as char).collect())) + } + }, + PyStringData::Utf16(data) => { + fn utf16_bytes(input: &[u16]) -> &[u8] { + unsafe { mem::transmute(input) } + } + match String::from_utf16(data) { + Ok(s) => Ok(Cow::Owned(s)), + Err(_) => Err(PyErr::from_instance( + py, try!(exc::UnicodeDecodeError::new( + py, cstr!("utf-16"), + utf16_bytes(data), 0 .. 2*data.len(), cstr!("invalid utf-16"))) + )) + } + }, + PyStringData::Utf32(data) => { + fn utf32_bytes(input: &[u32]) -> &[u8] { + unsafe { mem::transmute(input) } + } + match data.iter().map(|&u| char::from_u32(u)).collect() { + Some(s) => Ok(Cow::Owned(s)), + None => Err(PyErr::from_instance( + py, try!(exc::UnicodeDecodeError::new( + py, cstr!("utf-32"), + utf32_bytes(data), 0 .. 4*data.len(), cstr!("invalid utf-32"))) + )) + } + } + } + } + + /// Convert the Python string data to a Rust string. + /// + /// Returns a borrow into the original string data if possible. + /// + /// Data that isn't valid in its encoding will be replaced + /// with U+FFFD REPLACEMENT CHARACTER. + pub fn to_string_lossy(self) -> Cow<'a, str> { + match self { + PyStringData::Utf8(data) => String::from_utf8_lossy(data), + PyStringData::Latin1(data) => { + if data.iter().all(|&b| b.is_ascii()) { + Cow::Borrowed(unsafe { str::from_utf8_unchecked(data) }) + } else { + Cow::Owned(data.iter().map(|&b| b as char).collect()) + } + }, + PyStringData::Utf16(data) => { + Cow::Owned(String::from_utf16_lossy(data)) + }, + PyStringData::Utf32(data) => { + Cow::Owned(data.iter() + .map(|&u| char::from_u32(u).unwrap_or('\u{FFFD}')) + .collect()) + } + } + } +} diff --git a/src/typeob.rs b/src/typeob.rs index 2a7e234e..4fb72ac7 100644 --- a/src/typeob.rs +++ b/src/typeob.rs @@ -201,11 +201,7 @@ pub fn initialize_type(py: Python, module_name: Option<&str>, type_name: &str } // async methods - if let Some(meth) = ::tp_as_async() { - type_object.tp_as_async = Box::into_raw(Box::new(meth)); - } else { - type_object.tp_as_async = 0 as *mut ffi::PyAsyncMethods; - } + async_methods::(type_object); // buffer protocol if let Some(meth) = ::tp_as_buffer() { @@ -244,6 +240,17 @@ pub fn initialize_type(py: Python, module_name: Option<&str>, type_name: &str } } +#[cfg(Py_3)] +fn async_methods(type_info: &mut ffi::PyTypeObject) { + if let Some(meth) = ::tp_as_async() { + type_info.tp_as_async = Box::into_raw(Box::new(meth)); + } else { + type_info.tp_as_async = 0 as *mut ffi::PyAsyncMethods; + } +} + +#[cfg(not(Py_3))] +fn async_methods(_type_info: &mut ffi::PyTypeObject) {} unsafe extern "C" fn tp_dealloc_callback(obj: *mut ffi::PyObject) where T: PyObjectAlloc @@ -295,9 +302,6 @@ fn py_class_method_defs() -> PyResult<(Option, for def in ::methods() { defs.push(def.as_method_def()); } - for def in ::methods() { - defs.push(def.as_method_def()); - } for def in ::methods() { defs.push(def.as_method_def()); } @@ -311,9 +315,20 @@ fn py_class_method_defs() -> PyResult<(Option, defs.push(def.as_method_def()); } + py_class_async_methods::(&mut defs); + Ok((new, call, defs)) } +#[cfg(Py_3)] +fn py_class_async_methods(defs: &mut Vec) { + for def in ::methods() { + defs.push(def.as_method_def()); + } +} + +#[cfg(not(Py_3))] +fn py_class_async_methods(_defs: &mut Vec) {} fn py_class_properties() -> Vec { let mut defs = HashMap::new();