|
88 | 88 | //!
|
89 | 89 | //! use pyo3_ffi::*;
|
90 | 90 | //!
|
91 |
| -//! #[allow(non_snake_case)] |
92 |
| -//! #[no_mangle] |
93 |
| -//! pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject { |
94 |
| -//! let init = PyModuleDef { |
95 |
| -//! m_base: PyModuleDef_HEAD_INIT, |
96 |
| -//! m_name: "string_sum\0".as_ptr() as *const c_char, |
97 |
| -//! m_doc: std::ptr::null(), |
98 |
| -//! m_size: 0, |
99 |
| -//! m_methods: std::ptr::null_mut(), |
100 |
| -//! m_slots: std::ptr::null_mut(), |
101 |
| -//! m_traverse: None, |
102 |
| -//! m_clear: None, |
103 |
| -//! m_free: None, |
104 |
| -//! }; |
105 |
| -//! |
106 |
| -//! let mptr = PyModule_Create(Box::into_raw(Box::new(init))); |
107 |
| -//! let version = env!("CARGO_PKG_VERSION"); |
108 |
| -//! PyModule_AddObject( |
109 |
| -//! mptr, |
110 |
| -//! "__version__\0".as_ptr() as *const c_char, |
111 |
| -//! PyUnicode_FromStringAndSize(version.as_ptr() as *const c_char, version.len() as isize), |
112 |
| -//! ); |
113 |
| -//! |
114 |
| -//! let wrapped_sum_as_string = PyMethodDef { |
115 |
| -//! ml_name: "sum_as_string\0".as_ptr() as *const c_char, |
| 91 | +//! static mut MODULE_DEF: PyModuleDef = PyModuleDef { |
| 92 | +//! m_base: PyModuleDef_HEAD_INIT, |
| 93 | +//! m_name: "string_sum\0".as_ptr().cast::<c_char>(), |
| 94 | +//! m_doc: "A Python module written in Rust.\0" |
| 95 | +//! .as_ptr() |
| 96 | +//! .cast::<c_char>(), |
| 97 | +//! m_size: 0, |
| 98 | +//! m_methods: unsafe { METHODS.as_mut_ptr().cast() }, |
| 99 | +//! m_slots: std::ptr::null_mut(), |
| 100 | +//! m_traverse: None, |
| 101 | +//! m_clear: None, |
| 102 | +//! m_free: None, |
| 103 | +//! }; |
| 104 | +//! |
| 105 | +//! static mut METHODS: [PyMethodDef; 2] = [ |
| 106 | +//! PyMethodDef { |
| 107 | +//! ml_name: "sum_as_string\0".as_ptr().cast::<c_char>(), |
116 | 108 | //! ml_meth: PyMethodDefPointer {
|
117 |
| -//! _PyCFunctionFast: sum_as_string |
| 109 | +//! _PyCFunctionFast: sum_as_string, |
118 | 110 | //! },
|
119 | 111 | //! ml_flags: METH_FASTCALL,
|
120 |
| -//! ml_doc: "returns the sum of two integers as a string\0".as_ptr() as *const c_char, |
121 |
| -//! }; |
122 |
| -//! |
123 |
| -//! // PyModule_AddObject can technically fail. |
124 |
| -//! // For more involved applications error checking may be necessary |
125 |
| -//! PyModule_AddObject( |
126 |
| -//! mptr, |
127 |
| -//! "sum_as_string\0".as_ptr() as *const c_char, |
128 |
| -//! PyCFunction_NewEx( |
129 |
| -//! Box::into_raw(Box::new(wrapped_sum_as_string)), |
130 |
| -//! std::ptr::null_mut(), |
131 |
| -//! PyUnicode_InternFromString("string_sum\0".as_ptr() as *const c_char), |
132 |
| -//! ), |
133 |
| -//! ); |
134 |
| -//! |
135 |
| -//! let all = ["__all__\0", "__version__\0", "sum_as_string\0"]; |
136 |
| -//! |
137 |
| -//! let pyall = PyTuple_New(all.len() as isize); |
138 |
| -//! for (i, obj) in all.iter().enumerate() { |
139 |
| -//! PyTuple_SET_ITEM( |
140 |
| -//! pyall, |
141 |
| -//! i as isize, |
142 |
| -//! PyUnicode_InternFromString(obj.as_ptr() as *const c_char), |
143 |
| -//! ) |
144 |
| -//! } |
145 |
| -//! |
146 |
| -//! PyModule_AddObject(mptr, "__all__\0".as_ptr() as *const c_char, pyall); |
147 |
| -//! |
148 |
| -//! mptr |
| 112 | +//! ml_doc: "returns the sum of two integers as a string\0" |
| 113 | +//! .as_ptr() |
| 114 | +//! .cast::<c_char>(), |
| 115 | +//! }, |
| 116 | +//! // A zeroed PyMethodDef to mark the end of the array. |
| 117 | +//! PyMethodDef::zeroed() |
| 118 | +//! ]; |
| 119 | +//! |
| 120 | +//! // The module initialization function, which must be named `PyInit_<your_module>`. |
| 121 | +//! #[allow(non_snake_case)] |
| 122 | +//! #[no_mangle] |
| 123 | +//! pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject { |
| 124 | +//! PyModule_Create(ptr::addr_of_mut!(MODULE_DEF)) |
149 | 125 | //! }
|
150 | 126 | //!
|
151 | 127 | //! pub unsafe extern "C" fn sum_as_string(
|
|
154 | 130 | //! nargs: Py_ssize_t,
|
155 | 131 | //! ) -> *mut PyObject {
|
156 | 132 | //! if nargs != 2 {
|
157 |
| -//! return raise_type_error("sum_as_string() expected 2 positional arguments"); |
| 133 | +//! PyErr_SetString( |
| 134 | +//! PyExc_TypeError, |
| 135 | +//! "sum_as_string() expected 2 positional arguments\0" |
| 136 | +//! .as_ptr() |
| 137 | +//! .cast::<c_char>(), |
| 138 | +//! ); |
| 139 | +//! return std::ptr::null_mut(); |
158 | 140 | //! }
|
159 | 141 | //!
|
160 | 142 | //! let arg1 = *args;
|
161 | 143 | //! if PyLong_Check(arg1) == 0 {
|
162 |
| -//! return raise_type_error("sum_as_string() expected an int for positional argument 1"); |
| 144 | +//! PyErr_SetString( |
| 145 | +//! PyExc_TypeError, |
| 146 | +//! "sum_as_string() expected an int for positional argument 1\0" |
| 147 | +//! .as_ptr() |
| 148 | +//! .cast::<c_char>(), |
| 149 | +//! ); |
| 150 | +//! return std::ptr::null_mut(); |
163 | 151 | //! }
|
164 | 152 | //!
|
165 | 153 | //! let arg1 = PyLong_AsLong(arg1);
|
166 | 154 | //! if !PyErr_Occurred().is_null() {
|
167 |
| -//! return ptr::null_mut() |
| 155 | +//! return ptr::null_mut(); |
168 | 156 | //! }
|
169 | 157 | //!
|
170 | 158 | //! let arg2 = *args.add(1);
|
171 | 159 | //! if PyLong_Check(arg2) == 0 {
|
172 |
| -//! return raise_type_error("sum_as_string() expected an int for positional argument 2"); |
| 160 | +//! PyErr_SetString( |
| 161 | +//! PyExc_TypeError, |
| 162 | +//! "sum_as_string() expected an int for positional argument 2\0" |
| 163 | +//! .as_ptr() |
| 164 | +//! .cast::<c_char>(), |
| 165 | +//! ); |
| 166 | +//! return std::ptr::null_mut(); |
173 | 167 | //! }
|
174 | 168 | //!
|
175 | 169 | //! let arg2 = PyLong_AsLong(arg2);
|
176 | 170 | //! if !PyErr_Occurred().is_null() {
|
177 |
| -//! return ptr::null_mut() |
| 171 | +//! return ptr::null_mut(); |
178 | 172 | //! }
|
179 |
| -//! let res = (arg1 + arg2).to_string(); |
180 |
| -//! PyUnicode_FromStringAndSize(res.as_ptr() as *const c_char, res.len() as isize) |
181 |
| -//! } |
182 | 173 | //!
|
183 |
| -//! #[cold] |
184 |
| -//! #[inline(never)] |
185 |
| -//! fn raise_type_error(msg: &str) -> *mut PyObject { |
186 |
| -//! unsafe { |
187 |
| -//! let err_msg = |
188 |
| -//! PyUnicode_FromStringAndSize(msg.as_ptr() as *const c_char, msg.len() as isize); |
189 |
| -//! PyErr_SetObject(PyExc_TypeError, err_msg); |
190 |
| -//! Py_DECREF(err_msg); |
191 |
| -//! }; |
192 |
| -//! std::ptr::null_mut() |
| 174 | +//! match arg1.checked_add(arg2) { |
| 175 | +//! Some(sum) => { |
| 176 | +//! let string = sum.to_string(); |
| 177 | +//! PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as isize) |
| 178 | +//! } |
| 179 | +//! None => { |
| 180 | +//! PyErr_SetString( |
| 181 | +//! PyExc_OverflowError, |
| 182 | +//! "arguments too large to add\0".as_ptr().cast::<c_char>(), |
| 183 | +//! ); |
| 184 | +//! std::ptr::null_mut() |
| 185 | +//! } |
| 186 | +//! } |
193 | 187 | //! }
|
194 | 188 | //! ```
|
195 | 189 | //!
|
|
0 commit comments