@@ -136,5 +136,297 @@ inline PyTypeObject* make_metatype() {
136
136
return type;
137
137
}
138
138
139
+ extern " C" inline PyObject *object_new (PyTypeObject *type, PyObject *, PyObject *) {
140
+ PyObject *self = type->tp_alloc (type, 0 );
141
+ auto instance = (instance_essentials<void > *) self;
142
+ auto tinfo = get_type_info (type);
143
+ instance->value = ::operator new (tinfo->type_size );
144
+ instance->owned = true ;
145
+ instance->holder_constructed = false ;
146
+ get_internals ().registered_instances .emplace (instance->value , self);
147
+ return self;
148
+ }
149
+
150
+ extern " C" inline int object_init (PyObject *self, PyObject *, PyObject *) {
151
+ PyTypeObject *type = Py_TYPE (self);
152
+ std::string msg;
153
+ #if defined(PYPY_VERSION)
154
+ msg += handle ((PyObject *) type).attr (" __module__" ).cast <std::string>() + " ." ;
155
+ #endif
156
+ msg += type->tp_name ;
157
+ msg += " : No constructor defined!" ;
158
+ PyErr_SetString (PyExc_TypeError, msg.c_str ());
159
+ return -1 ;
160
+ }
161
+
162
+ extern " C" inline void object_dealloc (PyObject *self) {
163
+ auto instance = (instance_essentials<void > *) self;
164
+ if (instance->value ) {
165
+ auto type = Py_TYPE (self);
166
+ get_type_info (type)->dealloc (self);
167
+
168
+ auto ®istered_instances = get_internals ().registered_instances ;
169
+ auto range = registered_instances.equal_range (instance->value );
170
+ bool found = false ;
171
+ for (auto it = range.first ; it != range.second ; ++it) {
172
+ if (type == Py_TYPE (it->second )) {
173
+ registered_instances.erase (it);
174
+ found = true ;
175
+ break ;
176
+ }
177
+ }
178
+ if (!found)
179
+ pybind11_fail (" object_dealloc(): Tried to deallocate unregistered instance!" );
180
+
181
+ if (instance->weakrefs )
182
+ PyObject_ClearWeakRefs (self);
183
+
184
+ PyObject **dict_ptr = _PyObject_GetDictPtr (self);
185
+ if (dict_ptr)
186
+ Py_CLEAR (*dict_ptr);
187
+ }
188
+ Py_TYPE (self)->tp_free (self);
189
+ }
190
+
191
+ extern " C" inline PyObject *object_get_dict (PyObject *self, void *) {
192
+ PyObject *&dict = *_PyObject_GetDictPtr (self);
193
+ if (!dict)
194
+ dict = PyDict_New ();
195
+ Py_XINCREF (dict);
196
+ return dict;
197
+ }
198
+
199
+ extern " C" inline int object_set_dict (PyObject *self, PyObject *new_dict, void *) {
200
+ if (!PyDict_Check (new_dict)) {
201
+ PyErr_Format (PyExc_TypeError, " __dict__ must be set to a dictionary, not a '%.200s'" ,
202
+ Py_TYPE (new_dict)->tp_name );
203
+ return -1 ;
204
+ }
205
+ PyObject *&dict = *_PyObject_GetDictPtr (self);
206
+ Py_INCREF (new_dict);
207
+ Py_CLEAR (dict);
208
+ dict = new_dict;
209
+ return 0 ;
210
+ }
211
+
212
+ static PyGetSetDef object_getset[] = {
213
+ {const_cast <char *>(" __dict__" ), object_get_dict, object_set_dict, nullptr , nullptr },
214
+ {nullptr , nullptr , nullptr , nullptr , nullptr }
215
+ };
216
+
217
+ extern " C" inline int object_traverse (PyObject *self, visitproc visit, void *arg) {
218
+ PyObject *&dict = *_PyObject_GetDictPtr (self);
219
+ Py_VISIT (dict);
220
+ return 0 ;
221
+ }
222
+
223
+ extern " C" inline int object_clear (PyObject *self) {
224
+ PyObject *&dict = *_PyObject_GetDictPtr (self);
225
+ Py_CLEAR (dict);
226
+ return 0 ;
227
+ }
228
+
229
+ extern " C" inline int object_getbuffer (PyObject *obj, Py_buffer *view, int flags) {
230
+ auto tinfo = get_type_info (Py_TYPE (obj));
231
+ if (view == nullptr || obj == nullptr || !tinfo || !tinfo->get_buffer ) {
232
+ if (view)
233
+ view->obj = nullptr ;
234
+ PyErr_SetString (PyExc_BufferError, " generic_type::getbuffer(): Internal error" );
235
+ return -1 ;
236
+ }
237
+ memset (view, 0 , sizeof (Py_buffer));
238
+ buffer_info *info = tinfo->get_buffer (obj, tinfo->get_buffer_data );
239
+ view->obj = obj;
240
+ view->ndim = 1 ;
241
+ view->internal = info;
242
+ view->buf = info->ptr ;
243
+ view->itemsize = (ssize_t ) info->itemsize ;
244
+ view->len = view->itemsize ;
245
+ for (auto s : info->shape )
246
+ view->len *= s;
247
+ if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
248
+ view->format = const_cast <char *>(info->format .c_str ());
249
+ if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
250
+ view->ndim = (int ) info->ndim ;
251
+ view->strides = (ssize_t *) &info->strides [0 ];
252
+ view->shape = (ssize_t *) &info->shape [0 ];
253
+ }
254
+ Py_INCREF (view->obj );
255
+ return 0 ;
256
+ }
257
+
258
+ extern " C" inline void object_releasebuffer (PyObject *, Py_buffer *view) {
259
+ delete (buffer_info *) view->internal ;
260
+ }
261
+
262
+ // / Creates a type which can be used as a common base for all classes with the same
263
+ // / instance size, i.e. all classes with the same `sizeof(holder_type)`. This is
264
+ // / needed in order to satisfy Python's requirements for multiple inheritance.
265
+ inline PyObject *make_object_base_type (size_t instance_size) {
266
+ auto name = " pybind11_object_" + std::to_string (instance_size);
267
+ auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING (name.c_str ()));
268
+
269
+ /* Danger zone: from now (and until PyType_Ready), make sure to
270
+ issue no Python C API calls which could potentially invoke the
271
+ garbage collector (the GC will call type_traverse(), which will in
272
+ turn find the newly constructed type in an invalid state) */
273
+ auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc (&PyType_Type, 0 );
274
+ if (!heap_type)
275
+ pybind11_fail (" make_object_base_type(): error allocating type!" );
276
+
277
+ heap_type->ht_name = name_obj.inc_ref ().ptr ();
278
+ #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
279
+ heap_type->ht_qualname = name_obj.inc_ref ().ptr ();
280
+ #endif
281
+
282
+ auto type = &heap_type->ht_type ;
283
+ type->tp_name = strdup (name.c_str ());
284
+ type->tp_base = &PyBaseObject_Type;
285
+ type->tp_basicsize = static_cast <ssize_t >(instance_size);
286
+ type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
287
+
288
+ type->tp_new = object_new;
289
+ type->tp_init = object_init;
290
+ type->tp_dealloc = object_dealloc;
291
+
292
+ /* Support weak references (needed for the keep_alive feature) */
293
+ type->tp_weaklistoffset = offsetof (instance_essentials<void >, weakrefs);
294
+
295
+ if (PyType_Ready (type) < 0 )
296
+ pybind11_fail (" PyType_Ready failed in make_object_base_type():" + error_string ());
297
+
298
+ assert (!PyType_HasFeature (type, Py_TPFLAGS_HAVE_GC));
299
+ return (PyObject *) heap_type;
300
+ }
301
+
302
+ inline PyObject *internals::get_base (size_t instance_size) {
303
+ auto it = bases.find (instance_size);
304
+ if (it != bases.end ()) {
305
+ return it->second ;
306
+ } else {
307
+ auto base = make_object_base_type (instance_size);
308
+ bases[instance_size] = base;
309
+ return base;
310
+ }
311
+ }
312
+
313
+ inline PyObject* make_new_python_type (const type_record &rec) {
314
+ auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING (rec.name ));
315
+
316
+ #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
317
+ auto ht_qualname = name;
318
+ if (rec.scope && hasattr (rec.scope , " __qualname__" )) {
319
+ ht_qualname = reinterpret_steal<object>(
320
+ PyUnicode_FromFormat (" %U.%U" , rec.scope .attr (" __qualname__" ).ptr (), name.ptr ()));
321
+ }
322
+ #endif
323
+
324
+ object module ;
325
+ if (rec.scope ) {
326
+ if (hasattr (rec.scope , " __module__" ))
327
+ module = rec.scope .attr (" __module__" );
328
+ else if (hasattr (rec.scope , " __name__" ))
329
+ module = rec.scope .attr (" __name__" );
330
+ }
331
+
332
+ #if !defined(PYPY_VERSION)
333
+ const auto full_name = module ? str (module ).cast <std::string>() + " ." + rec.name
334
+ : std::string (rec.name );
335
+ #else
336
+ const auto full_name = std::string (rec.name );
337
+ #endif
338
+
339
+ char *tp_doc = nullptr ;
340
+ if (rec.doc && options::show_user_defined_docstrings ()) {
341
+ /* Allocate memory for docstring (using PyObject_MALLOC, since
342
+ Python will free this later on) */
343
+ size_t size = strlen (rec.doc ) + 1 ;
344
+ tp_doc = (char *) PyObject_MALLOC (size);
345
+ memcpy ((void *) tp_doc, rec.doc , size);
346
+ }
347
+
348
+ auto &internals = get_internals ();
349
+ auto bases = tuple (rec.bases );
350
+ auto base = (bases.size () == 0 ) ? internals.get_base (rec.instance_size )
351
+ : bases[0 ].ptr ();
352
+
353
+ /* Danger zone: from now (and until PyType_Ready), make sure to
354
+ issue no Python C API calls which could potentially invoke the
355
+ garbage collector (the GC will call type_traverse(), which will in
356
+ turn find the newly constructed type in an invalid state) */
357
+ auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc (&PyType_Type, 0 );
358
+ if (!heap_type)
359
+ pybind11_fail (std::string (rec.name ) + " : Unable to create type object!" );
360
+
361
+ heap_type->ht_name = name.release ().ptr ();
362
+ #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
363
+ heap_type->ht_qualname = ht_qualname.release ().ptr ();
364
+ #endif
365
+
366
+ auto type = &heap_type->ht_type ;
367
+ type->tp_name = strdup (full_name.c_str ());
368
+ type->tp_doc = tp_doc;
369
+ type->tp_base = (PyTypeObject *) handle (base).inc_ref ().ptr ();
370
+ type->tp_basicsize = static_cast <ssize_t >(rec.instance_size );
371
+ if (bases.size () > 0 )
372
+ type->tp_bases = bases.release ().ptr ();
373
+
374
+ /* Custom metaclass if requested (used for static properties) */
375
+ if (rec.metaclass ) {
376
+ Py_INCREF (internals.metatype );
377
+ Py_TYPE (type) = (PyTypeObject *) internals.metatype ;
378
+ }
379
+
380
+ /* Supported protocols */
381
+ type->tp_as_number = &heap_type->as_number ;
382
+ type->tp_as_sequence = &heap_type->as_sequence ;
383
+ type->tp_as_mapping = &heap_type->as_mapping ;
384
+
385
+ /* Flags */
386
+ type->tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
387
+ #if PY_MAJOR_VERSION < 3
388
+ type->tp_flags |= Py_TPFLAGS_CHECKTYPES;
389
+ #endif
390
+
391
+ /* Support dynamic attributes */
392
+ if (rec.dynamic_attr ) {
393
+ #if defined(PYPY_VERSION)
394
+ pybind11_fail (std::string (rec.name ) + " : dynamic attributes are "
395
+ " currently not supported in "
396
+ " conjunction with PyPy!" );
397
+ #endif
398
+ type->tp_dictoffset = type->tp_basicsize ; // place dict at the end
399
+ type->tp_basicsize += sizeof (PyObject *); // and allocate enough space for it
400
+ type->tp_getset = object_getset;
401
+ type->tp_traverse = object_traverse;
402
+ type->tp_clear = object_clear;
403
+ type->tp_flags |= Py_TPFLAGS_HAVE_GC;
404
+ }
405
+
406
+ if (rec.buffer_protocol ) {
407
+ type->tp_as_buffer = &heap_type->as_buffer ;
408
+ #if PY_MAJOR_VERSION < 3
409
+ type->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
410
+ #endif
411
+ heap_type->as_buffer .bf_getbuffer = object_getbuffer;
412
+ heap_type->as_buffer .bf_releasebuffer = object_releasebuffer;
413
+ }
414
+
415
+ if (PyType_Ready (type) < 0 )
416
+ pybind11_fail (std::string (rec.name ) + " : PyType_Ready failed (" + error_string () + " )!" );
417
+
418
+ assert (rec.dynamic_attr ? PyType_HasFeature (type, Py_TPFLAGS_HAVE_GC)
419
+ : !PyType_HasFeature (type, Py_TPFLAGS_HAVE_GC));
420
+
421
+ /* Register type with the parent scope */
422
+ if (rec.scope )
423
+ setattr (rec.scope , rec.name , (PyObject *) type);
424
+
425
+ if (module ) // Needed by pydoc
426
+ setattr ((PyObject *) type, " __module__" , module );
427
+
428
+ return (PyObject *) type;
429
+ }
430
+
139
431
NAMESPACE_END (detail)
140
432
NAMESPACE_END(pybind11)
0 commit comments