Skip to content

Commit 6e56d93

Browse files
Add integer c-api support (#7905)
* Add integer c-api support * Fix `PyLong_AsUnsignedLongLong` return value * Fix error message * Add type check functions
1 parent 20cb884 commit 6e56d93

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

crates/capi/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern crate alloc;
1111
pub mod abstract_;
1212
pub mod bytesobject;
1313
pub mod import;
14+
pub mod longobject;
1415
pub mod object;
1516
pub mod pyerrors;
1617
pub mod pylifecycle;

crates/capi/src/longobject.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use crate::PyObject;
2+
use crate::object::define_py_check;
3+
use crate::pystate::with_vm;
4+
use core::ffi::{c_long, c_longlong, c_ulong, c_ulonglong};
5+
use rustpython_vm::PyResult;
6+
use rustpython_vm::builtins::PyInt;
7+
8+
define_py_check!(fn PyLong_Check, types.int_type);
9+
define_py_check!(exact fn PyLong_CheckExact, types.int_type);
10+
11+
#[unsafe(no_mangle)]
12+
pub extern "C" fn PyLong_FromLong(value: c_long) -> *mut PyObject {
13+
with_vm(|vm| vm.ctx.new_int(value))
14+
}
15+
16+
#[unsafe(no_mangle)]
17+
pub extern "C" fn PyLong_FromLongLong(value: c_longlong) -> *mut PyObject {
18+
with_vm(|vm| vm.ctx.new_int(value))
19+
}
20+
21+
#[unsafe(no_mangle)]
22+
pub extern "C" fn PyLong_FromSsize_t(value: isize) -> *mut PyObject {
23+
with_vm(|vm| vm.ctx.new_int(value))
24+
}
25+
26+
#[unsafe(no_mangle)]
27+
pub extern "C" fn PyLong_FromSize_t(value: usize) -> *mut PyObject {
28+
with_vm(|vm| vm.ctx.new_int(value))
29+
}
30+
31+
#[unsafe(no_mangle)]
32+
pub extern "C" fn PyLong_FromUnsignedLong(value: c_ulong) -> *mut PyObject {
33+
with_vm(|vm| vm.ctx.new_int(value))
34+
}
35+
36+
#[unsafe(no_mangle)]
37+
pub extern "C" fn PyLong_FromUnsignedLongLong(value: c_ulonglong) -> *mut PyObject {
38+
with_vm(|vm| vm.ctx.new_int(value))
39+
}
40+
41+
#[unsafe(no_mangle)]
42+
pub unsafe extern "C" fn PyLong_AsLong(obj: *mut PyObject) -> c_long {
43+
with_vm::<PyResult<c_long>, _>(|vm| {
44+
unsafe { &*obj }
45+
.to_owned()
46+
.try_index(vm)?
47+
.as_bigint()
48+
.try_into()
49+
.map_err(|_| vm.new_overflow_error("Python int too large to convert to C long"))
50+
})
51+
}
52+
53+
#[unsafe(no_mangle)]
54+
pub unsafe extern "C" fn PyLong_AsUnsignedLongLong(obj: *mut PyObject) -> c_ulonglong {
55+
with_vm::<PyResult<c_ulonglong>, _>(|vm| {
56+
unsafe { &*obj }
57+
.to_owned()
58+
.try_downcast::<PyInt>(vm)?
59+
.as_bigint()
60+
.try_into()
61+
.map_err(|_| {
62+
vm.new_overflow_error("Python int too large to convert to C unsigned long long")
63+
})
64+
})
65+
}
66+
67+
#[cfg(false)]
68+
mod tests {
69+
use pyo3::prelude::*;
70+
use pyo3::types::PyInt;
71+
72+
#[test]
73+
fn test_py_int_u32() {
74+
Python::attach(|py| {
75+
let number = PyInt::new(py, 123);
76+
assert!(number.is_instance_of::<PyInt>());
77+
assert_eq!(number.extract::<i32>().unwrap(), 123);
78+
})
79+
}
80+
81+
#[test]
82+
fn test_py_int_u64() {
83+
Python::attach(|py| {
84+
let number = PyInt::new(py, 123u64);
85+
assert!(number.is_instance_of::<PyInt>());
86+
assert_eq!(number.extract::<u64>().unwrap(), 123);
87+
})
88+
}
89+
}

crates/capi/src/util.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::PyObject;
22
use core::convert::Infallible;
3-
use core::ffi::{c_char, c_double, c_int, c_long, c_void};
3+
use core::ffi::{c_char, c_double, c_int, c_long, c_ulonglong, c_void};
44
use rustpython_vm::{PyObjectRef, PyRef, PyResult, VirtualMachine};
55

66
pub(crate) trait FfiResult<Output = Self> {
@@ -93,6 +93,14 @@ impl FfiResult for c_long {
9393
}
9494
}
9595

96+
impl FfiResult for c_ulonglong {
97+
const ERR_VALUE: Self = Self::MAX;
98+
99+
fn into_output(self, _vm: &VirtualMachine) -> Self {
100+
self
101+
}
102+
}
103+
96104
impl FfiResult for c_double {
97105
const ERR_VALUE: Self = -1.0;
98106

0 commit comments

Comments
 (0)