@@ -49,64 +49,40 @@ use std::ptr;
49
49
50
50
use pyo3_ffi :: * ;
51
51
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 >(),
77
69
ml_meth : PyMethodDefPointer {
78
- _PyCFunctionFast : sum_as_string
70
+ _PyCFunctionFast : sum_as_string ,
79
71
},
80
72
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 ))
110
86
}
111
87
112
88
pub unsafe extern " C" fn sum_as_string (
@@ -115,45 +91,60 @@ pub unsafe extern "C" fn sum_as_string(
115
91
nargs : Py_ssize_t ,
116
92
) -> * mut PyObject {
117
93
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 ();
119
101
}
120
102
121
103
let arg1 = * args ;
122
104
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 ();
124
112
}
125
113
126
114
let arg1 = PyLong_AsLong (arg1 );
127
115
if ! PyErr_Occurred (). is_null () {
128
- return ptr :: null_mut ()
116
+ return ptr :: null_mut ();
129
117
}
130
118
131
119
let arg2 = * args . add (1 );
132
120
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 ();
134
128
}
135
129
136
130
let arg2 = PyLong_AsLong (arg2 );
137
131
if ! PyErr_Occurred (). is_null () {
138
- return ptr :: null_mut ()
132
+ return ptr :: null_mut ();
139
133
}
140
134
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
+ }
157
148
}
158
149
```
159
150
0 commit comments