@@ -103,6 +103,37 @@ sampledtype_ensure_canonical(SampleDTypeObject *self) {
103
103
return self ;
104
104
}
105
105
106
+ static PyObject * create_element_view (SampleDTypeObject * descr , char * dataptr ,
107
+ npy_bool readonly ) {
108
+ PyObject * ndarr_obj = PyObject_GetAttrString (descr -> sample_scalar , "ndarr" );
109
+ if (ndarr_obj == NULL ) {
110
+ return NULL ;
111
+ }
112
+ if (!PyArray_Check (ndarr_obj )) {
113
+ Py_DECREF (ndarr_obj );
114
+ PyErr_SetString (PyExc_TypeError ,
115
+ "SampleScalar.ndarr() must return NumPy array" );
116
+ return NULL ;
117
+ }
118
+
119
+ PyArrayObject * ndarr_arrobj = (PyArrayObject * )ndarr_obj ;
120
+ PyArray_Descr * ndarr_descr = PyArray_DESCR (ndarr_arrobj );
121
+
122
+ PyObject * view = PyArray_NewFromDescr (
123
+ & PyArray_Type , ndarr_descr , PyArray_NDIM (ndarr_arrobj ),
124
+ PyArray_DIMS (ndarr_arrobj ), PyArray_STRIDES (ndarr_arrobj ),
125
+ dataptr , // data pointer for the view
126
+ readonly ? 0 : NPY_ARRAY_WRITEABLE , NULL );
127
+ if (view != NULL ) {
128
+ // Now 'view' owns the descriptor, it will be dereferenced when view is
129
+ // deallocated
130
+ Py_INCREF (ndarr_descr );
131
+ }
132
+
133
+ Py_DECREF (ndarr_obj );
134
+ return view ;
135
+ }
136
+
106
137
static int sampledtype_setitem (SampleDTypeObject * descr , PyObject * obj ,
107
138
char * dataptr ) {
108
139
printf ("%s, target elsise %lld, type_num %d\n" , __func__ , descr -> base .elsize ,
@@ -127,29 +158,17 @@ static int sampledtype_setitem(SampleDTypeObject *descr, PyObject *obj,
127
158
return -1 ;
128
159
}
129
160
130
- // Copy data-bytes from 'obj' into 'dataptr'
131
- PyObject * ndarr_bytes = PyObject_GetAttrString (obj , "data_buffer" );
132
- if (ndarr_bytes == NULL ) {
161
+ PyObject * view = create_element_view (descr , dataptr , NPY_FALSE );
162
+ if (view == NULL ) {
133
163
return -1 ;
134
164
}
135
165
136
- const char * src_data = NULL ;
137
- Py_ssize_t data_size = 0 ;
138
- if (PyBytes_AsStringAndSize (ndarr_bytes , & src_data , & data_size ) != 0 ) {
139
- Py_DECREF (ndarr_bytes );
140
- return -1 ;
141
- }
142
-
143
- if (data_size != descr -> base .elsize ) {
144
- Py_DECREF (ndarr_bytes );
145
- PyErr_Format (PyExc_ValueError ,
146
- "Unexpected item data buffer size: %zd / %zd" , data_size ,
147
- descr -> base .elsize );
166
+ res = PyObject_CallMethod (obj , "setitem" , "O" , view );
167
+ Py_DECREF (view );
168
+ if (res == NULL ) {
148
169
return -1 ;
149
170
}
150
-
151
- memcpy (dataptr , src_data , data_size );
152
- Py_DECREF (ndarr_bytes );
171
+ Py_DECREF (res );
153
172
154
173
return 0 ;
155
174
}
@@ -158,16 +177,17 @@ static PyObject *sampledtype_getitem(SampleDTypeObject *descr, char *dataptr) {
158
177
printf ("%s, source elsize %lld, type_num %d\n" , __func__ , descr -> base .elsize ,
159
178
descr -> base .type_num );
160
179
161
- // Pass data-bytes from 'dataptr' to 'obj'
162
- PyObject * ndarr_bytes =
163
- PyBytes_FromStringAndSize (dataptr , descr -> base .elsize );
164
- if (ndarr_bytes == NULL ) {
180
+ PyObject * view = create_element_view (descr , dataptr , NPY_TRUE );
181
+ if (view == NULL ) {
165
182
return NULL ;
166
183
}
167
184
168
- PyObject * res = PyObject_CallMethod (descr -> sample_scalar , "from_data_buffer" ,
169
- "O" , ndarr_bytes );
170
- Py_DECREF (ndarr_bytes );
185
+ PyObject * res =
186
+ PyObject_CallMethod (descr -> sample_scalar , "getitem" , "O" , view );
187
+ Py_DECREF (view );
188
+ if (res == NULL ) {
189
+ return NULL ;
190
+ }
171
191
172
192
return res ;
173
193
}
0 commit comments