Skip to content

Commit f574168

Browse files
authored
Merge pull request #2586 from mejrs/ffi2
ffi - Also update the readme
2 parents 0935ddc + 26fe75e commit f574168

File tree

1 file changed

+67
-76
lines changed

1 file changed

+67
-76
lines changed

pyo3-ffi/README.md

Lines changed: 67 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -49,64 +49,40 @@ use std::ptr;
4949

5050
use pyo3_ffi::*;
5151

52-
#[allow(non_snake_case)]
53-
#[no_mangle]
54-
pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject {
55-
let init = PyModuleDef {
56-
m_base: PyModuleDef_HEAD_INIT,
57-
m_name: "string_sum\0".as_ptr() as *const c_char,
58-
m_doc: std::ptr::null(),
59-
m_size: 0,
60-
m_methods: std::ptr::null_mut(),
61-
m_slots: std::ptr::null_mut(),
62-
m_traverse: None,
63-
m_clear: None,
64-
m_free: None,
65-
};
66-
67-
let mptr = PyModule_Create(Box::into_raw(Box::new(init)));
68-
let version = env!("CARGO_PKG_VERSION");
69-
PyModule_AddObject(
70-
mptr,
71-
"__version__\0".as_ptr() as *const c_char,
72-
PyUnicode_FromStringAndSize(version.as_ptr() as *const c_char, version.len() as isize),
73-
);
74-
75-
let wrapped_sum_as_string = PyMethodDef {
76-
ml_name: "sum_as_string\0".as_ptr() as *const c_char,
52+
static mut MODULE_DEF: PyModuleDef = PyModuleDef {
53+
m_base: PyModuleDef_HEAD_INIT,
54+
m_name: "string_sum\0".as_ptr().cast::<c_char>(),
55+
m_doc: "A Python module written in Rust.\0"
56+
.as_ptr()
57+
.cast::<c_char>(),
58+
m_size: 0,
59+
m_methods: unsafe { METHODS.as_mut_ptr().cast() },
60+
m_slots: std::ptr::null_mut(),
61+
m_traverse: None,
62+
m_clear: None,
63+
m_free: None,
64+
};
65+
66+
static mut METHODS: [PyMethodDef; 2] = [
67+
PyMethodDef {
68+
ml_name: "sum_as_string\0".as_ptr().cast::<c_char>(),
7769
ml_meth: PyMethodDefPointer {
78-
_PyCFunctionFast: sum_as_string
70+
_PyCFunctionFast: sum_as_string,
7971
},
8072
ml_flags: METH_FASTCALL,
81-
ml_doc: "returns the sum of two integers as a string\0".as_ptr() as *const c_char,
82-
};
83-
84-
// PyModule_AddObject can technically fail.
85-
// For more involved applications error checking may be necessary
86-
PyModule_AddObject(
87-
mptr,
88-
"sum_as_string\0".as_ptr() as *const c_char,
89-
PyCFunction_NewEx(
90-
Box::into_raw(Box::new(wrapped_sum_as_string)),
91-
std::ptr::null_mut(),
92-
PyUnicode_InternFromString("string_sum\0".as_ptr() as *const c_char),
93-
),
94-
);
95-
96-
let all = ["__all__\0", "__version__\0", "sum_as_string\0"];
97-
98-
let pyall = PyTuple_New(all.len() as isize);
99-
for (i, obj) in all.iter().enumerate() {
100-
PyTuple_SET_ITEM(
101-
pyall,
102-
i as isize,
103-
PyUnicode_InternFromString(obj.as_ptr() as *const c_char),
104-
)
105-
}
106-
107-
PyModule_AddObject(mptr, "__all__\0".as_ptr() as *const c_char, pyall);
108-
109-
mptr
73+
ml_doc: "returns the sum of two integers as a string\0"
74+
.as_ptr()
75+
.cast::<c_char>(),
76+
},
77+
// A zeroed PyMethodDef to mark the end of the array.
78+
PyMethodDef::zeroed()
79+
];
80+
81+
// The module initialization function, which must be named `PyInit_<your_module>`.
82+
#[allow(non_snake_case)]
83+
#[no_mangle]
84+
pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject {
85+
PyModule_Create(ptr::addr_of_mut!(MODULE_DEF))
11086
}
11187

11288
pub unsafe extern "C" fn sum_as_string(
@@ -115,45 +91,60 @@ pub unsafe extern "C" fn sum_as_string(
11591
nargs: Py_ssize_t,
11692
) -> *mut PyObject {
11793
if nargs != 2 {
118-
return raise_type_error("sum_as_string() expected 2 positional arguments");
94+
PyErr_SetString(
95+
PyExc_TypeError,
96+
"sum_as_string() expected 2 positional arguments\0"
97+
.as_ptr()
98+
.cast::<c_char>(),
99+
);
100+
return std::ptr::null_mut();
119101
}
120102

121103
let arg1 = *args;
122104
if PyLong_Check(arg1) == 0 {
123-
return raise_type_error("sum_as_string() expected an int for positional argument 1");
105+
PyErr_SetString(
106+
PyExc_TypeError,
107+
"sum_as_string() expected an int for positional argument 1\0"
108+
.as_ptr()
109+
.cast::<c_char>(),
110+
);
111+
return std::ptr::null_mut();
124112
}
125113

126114
let arg1 = PyLong_AsLong(arg1);
127115
if !PyErr_Occurred().is_null() {
128-
return ptr::null_mut()
116+
return ptr::null_mut();
129117
}
130118

131119
let arg2 = *args.add(1);
132120
if PyLong_Check(arg2) == 0 {
133-
return raise_type_error("sum_as_string() expected an int for positional argument 2");
121+
PyErr_SetString(
122+
PyExc_TypeError,
123+
"sum_as_string() expected an int for positional argument 2\0"
124+
.as_ptr()
125+
.cast::<c_char>(),
126+
);
127+
return std::ptr::null_mut();
134128
}
135129

136130
let arg2 = PyLong_AsLong(arg2);
137131
if !PyErr_Occurred().is_null() {
138-
return ptr::null_mut()
132+
return ptr::null_mut();
139133
}
140134

141-
142-
143-
let res = (arg1 + arg2).to_string();
144-
PyUnicode_FromStringAndSize(res.as_ptr() as *const c_char, res.len() as isize)
145-
}
146-
147-
#[cold]
148-
#[inline(never)]
149-
fn raise_type_error(msg: &str) -> *mut PyObject {
150-
unsafe {
151-
let err_msg =
152-
PyUnicode_FromStringAndSize(msg.as_ptr() as *const c_char, msg.len() as isize);
153-
PyErr_SetObject(PyExc_TypeError, err_msg);
154-
Py_DECREF(err_msg);
155-
};
156-
std::ptr::null_mut()
135+
match arg1.checked_add(arg2) {
136+
Some(sum) => {
137+
let string = sum.to_string();
138+
PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as isize)
139+
}
140+
None => {
141+
PyErr_SetString(
142+
PyExc_OverflowError,
143+
"arguments too large to add\0".as_ptr().cast::<c_char>(),
144+
);
145+
std::ptr::null_mut()
146+
}
147+
}
157148
}
158149
```
159150

0 commit comments

Comments
 (0)