13 #define _STRINGIFY_VERSION(a, b) (#a "." #b)
14 #define STRINGIFY_VERSION(a, b) _STRINGIFY_VERSION(a, b)
21 void DTOOL_Call_ExtractThisPointerForType(PyObject *
self, Dtool_PyTypedObject *classdef,
void **answer) {
22 if (DtoolInstance_Check(
self)) {
23 *answer = DtoolInstance_UPCAST(
self, *classdef);
34 bool Dtool_Call_ExtractThisPointer(PyObject *
self, Dtool_PyTypedObject &classdef,
void **answer) {
35 if (
self ==
nullptr || !DtoolInstance_Check(
self) || DtoolInstance_VOID_PTR(
self) ==
nullptr) {
36 Dtool_Raise_TypeError(
"C++ object is not yet constructed, or already destructed.");
40 *answer = DtoolInstance_UPCAST(
self, classdef);
52 bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *
self, Dtool_PyTypedObject &classdef,
53 void **answer,
const char *method_name) {
55 if (
self ==
nullptr || !DtoolInstance_Check(
self) || DtoolInstance_VOID_PTR(
self) ==
nullptr) {
56 Dtool_Raise_TypeError(
"C++ object is not yet constructed, or already destructed.");
60 if (DtoolInstance_IS_CONST(
self)) {
62 PyErr_Format(PyExc_TypeError,
63 "Cannot call %s() on a const object.",
68 *answer = DtoolInstance_UPCAST(
self, classdef);
95 DTOOL_Call_GetPointerThisClass(PyObject *
self, Dtool_PyTypedObject *classdef,
96 int param,
const string &function_name,
bool const_ok,
99 if (
self ==
nullptr) {
101 return Dtool_Raise_TypeError(
"self is nullptr");
106 if (DtoolInstance_Check(
self)) {
107 void *result = DtoolInstance_UPCAST(
self, *classdef);
109 if (result !=
nullptr) {
110 if (const_ok || !DtoolInstance_IS_CONST(
self)) {
115 return PyErr_Format(PyExc_TypeError,
116 "%s() argument %d may not be const",
117 function_name.c_str(), param);
124 return Dtool_Raise_ArgTypeError(
self, param, function_name.c_str(), classdef->_PyType.tp_name);
140 bool _Dtool_CheckErrorOccurred() {
141 if (_PyErr_OCCURRED()) {
145 Dtool_Raise_AssertionError();
155 PyObject *Dtool_Raise_AssertionError() {
157 #if PY_MAJOR_VERSION >= 3
162 Py_INCREF(PyExc_AssertionError);
163 PyErr_Restore(PyExc_AssertionError, message,
nullptr);
171 PyObject *Dtool_Raise_TypeError(
const char *message) {
174 Py_INCREF(PyExc_TypeError);
175 #if PY_MAJOR_VERSION >= 3
176 PyErr_Restore(PyExc_TypeError, PyUnicode_FromString(message),
nullptr);
178 PyErr_Restore(PyExc_TypeError, PyString_FromString(message),
nullptr);
190 PyObject *Dtool_Raise_ArgTypeError(PyObject *obj,
int param,
const char *function_name,
const char *type_name) {
191 #if PY_MAJOR_VERSION >= 3
192 PyObject *message = PyUnicode_FromFormat(
194 PyObject *message = PyString_FromFormat(
196 "%s() argument %d must be %s, not %s",
197 function_name, param, type_name,
198 Py_TYPE(obj)->tp_name);
200 Py_INCREF(PyExc_TypeError);
201 PyErr_Restore(PyExc_TypeError, message,
nullptr);
211 PyObject *Dtool_Raise_AttributeError(PyObject *obj,
const char *attribute) {
212 #if PY_MAJOR_VERSION >= 3
213 PyObject *message = PyUnicode_FromFormat(
215 PyObject *message = PyString_FromFormat(
217 "'%.100s' object has no attribute '%.200s'",
218 Py_TYPE(obj)->tp_name, attribute);
220 Py_INCREF(PyExc_AttributeError);
221 PyErr_Restore(PyExc_AttributeError, message,
nullptr);
235 PyObject *_Dtool_Raise_BadArgumentsError() {
236 return Dtool_Raise_TypeError(
"arguments do not match any function overload");
243 PyObject *_Dtool_Return_None() {
244 if (UNLIKELY(_PyErr_OCCURRED())) {
248 if (UNLIKELY(
Notify::ptr()->has_assert_failed())) {
249 return Dtool_Raise_AssertionError();
260 PyObject *Dtool_Return_Bool(
bool value) {
261 if (UNLIKELY(_PyErr_OCCURRED())) {
265 if (UNLIKELY(
Notify::ptr()->has_assert_failed())) {
266 return Dtool_Raise_AssertionError();
269 PyObject *result = (value ? Py_True : Py_False);
279 PyObject *_Dtool_Return(PyObject *value) {
280 if (UNLIKELY(_PyErr_OCCURRED())) {
284 if (UNLIKELY(
Notify::ptr()->has_assert_failed())) {
285 return Dtool_Raise_AssertionError();
291 #if PY_VERSION_HEX < 0x03040000
295 static PyObject *Dtool_EnumType_New(PyTypeObject *subtype, PyObject *args, PyObject *kwds) {
297 if (!Dtool_ExtractArg(&arg, args, kwds,
"value")) {
298 return PyErr_Format(PyExc_TypeError,
299 "%s() missing 1 required argument: 'value'",
303 if (Py_TYPE(arg) == subtype) {
308 PyObject *value2member = PyDict_GetItemString(subtype->tp_dict,
"_value2member_map_");
309 nassertr_always(value2member !=
nullptr,
nullptr);
311 PyObject *member = PyDict_GetItem(value2member, arg);
312 if (member !=
nullptr) {
317 PyObject *repr = PyObject_Repr(arg);
318 PyErr_Format(PyExc_ValueError,
"%s is not a valid %s",
319 #
if PY_MAJOR_VERSION >= 3
320 PyUnicode_AS_STRING(repr),
322 PyString_AS_STRING(repr),
329 static PyObject *Dtool_EnumType_Str(PyObject *
self) {
330 PyObject *name = PyObject_GetAttrString(
self,
"name");
331 #if PY_MAJOR_VERSION >= 3
332 PyObject *repr = PyUnicode_FromFormat(
"%s.%s", Py_TYPE(
self)->tp_name, PyString_AS_STRING(name));
334 PyObject *repr = PyString_FromFormat(
"%s.%s", Py_TYPE(
self)->tp_name, PyString_AS_STRING(name));
340 static PyObject *Dtool_EnumType_Repr(PyObject *
self) {
341 PyObject *name = PyObject_GetAttrString(
self,
"name");
342 PyObject *value = PyObject_GetAttrString(
self,
"value");
343 #if PY_MAJOR_VERSION >= 3
344 PyObject *repr = PyUnicode_FromFormat(
"<%s.%s: %ld>", Py_TYPE(
self)->tp_name, PyString_AS_STRING(name), PyLongOrInt_AS_LONG(value));
346 PyObject *repr = PyString_FromFormat(
"<%s.%s: %ld>", Py_TYPE(
self)->tp_name, PyString_AS_STRING(name), PyLongOrInt_AS_LONG(value));
358 PyTypeObject *Dtool_EnumType_Create(
const char *name, PyObject *names,
const char *module) {
359 static PyObject *enum_class =
nullptr;
360 #if PY_VERSION_HEX >= 0x03040000
361 static PyObject *enum_meta =
nullptr;
362 static PyObject *enum_create =
nullptr;
363 if (enum_meta ==
nullptr) {
364 PyObject *enum_module = PyImport_ImportModule(
"enum");
365 nassertr_always(enum_module !=
nullptr,
nullptr);
367 enum_class = PyObject_GetAttrString(enum_module,
"Enum");
368 enum_meta = PyObject_GetAttrString(enum_module,
"EnumMeta");
369 enum_create = PyObject_GetAttrString(enum_meta,
"_create_");
370 nassertr(enum_meta !=
nullptr,
nullptr);
373 PyObject *result = PyObject_CallFunction(enum_create, (
char *)
"OsN", enum_class, name, names);
374 nassertr(result !=
nullptr,
nullptr);
376 static PyObject *name_str;
377 static PyObject *name_sunder_str;
378 static PyObject *value_str;
379 static PyObject *value_sunder_str;
380 static PyObject *value2member_map_sunder_str;
382 if (enum_class ==
nullptr) {
383 #if PY_MAJOR_VERSION >= 3
384 name_str = PyUnicode_InternFromString(
"name");
385 value_str = PyUnicode_InternFromString(
"value");
386 name_sunder_str = PyUnicode_InternFromString(
"_name_");
387 value_sunder_str = PyUnicode_InternFromString(
"_value_");
388 value2member_map_sunder_str = PyUnicode_InternFromString(
"_value2member_map_");
390 name_str = PyString_InternFromString(
"name");
391 value_str = PyString_InternFromString(
"value");
392 name_sunder_str = PyString_InternFromString(
"_name_");
393 value_sunder_str = PyString_InternFromString(
"_value_");
394 value2member_map_sunder_str = PyString_InternFromString(
"_value2member_map_");
396 PyObject *name_value_tuple = PyTuple_New(4);
397 PyTuple_SET_ITEM(name_value_tuple, 0, name_str);
398 PyTuple_SET_ITEM(name_value_tuple, 1, value_str);
399 PyTuple_SET_ITEM(name_value_tuple, 2, name_sunder_str);
400 PyTuple_SET_ITEM(name_value_tuple, 3, value_sunder_str);
402 Py_INCREF(value_str);
404 PyObject *slots_dict = PyDict_New();
405 PyDict_SetItemString(slots_dict,
"__slots__", name_value_tuple);
406 Py_DECREF(name_value_tuple);
408 enum_class = PyObject_CallFunction((PyObject *)&PyType_Type, (
char *)
"s()N",
"Enum", slots_dict);
409 nassertr(enum_class !=
nullptr,
nullptr);
413 PyObject *value2member = PyDict_New();
414 PyObject *dict = PyDict_New();
415 PyDict_SetItem(dict, value2member_map_sunder_str, value2member);
416 PyObject *result = PyObject_CallFunction((PyObject *)&PyType_Type, (
char *)
"s(O)N", name, enum_class, dict);
417 nassertr(result !=
nullptr,
nullptr);
419 ((PyTypeObject *)result)->tp_new = Dtool_EnumType_New;
420 ((PyTypeObject *)result)->tp_str = Dtool_EnumType_Str;
421 ((PyTypeObject *)result)->tp_repr = Dtool_EnumType_Repr;
423 PyObject *empty_tuple = PyTuple_New(0);
427 Py_ssize_t size = PyTuple_GET_SIZE(names);
428 for (Py_ssize_t i = 0; i < size; ++i) {
429 PyObject *item = PyTuple_GET_ITEM(names, i);
430 PyObject *name = PyTuple_GET_ITEM(item, 0);
431 PyObject *value = PyTuple_GET_ITEM(item, 1);
432 PyObject *member = PyType_GenericNew((PyTypeObject *)result, empty_tuple,
nullptr);
433 PyObject_SetAttr(member, name_str, name);
434 PyObject_SetAttr(member, name_sunder_str, name);
435 PyObject_SetAttr(member, value_str, value);
436 PyObject_SetAttr(member, value_sunder_str, value);
437 PyObject_SetAttr(result, name, member);
438 PyDict_SetItem(value2member, value, member);
442 Py_DECREF(value2member);
443 Py_DECREF(empty_tuple);
446 if (module !=
nullptr) {
447 PyObject *modstr = PyUnicode_FromString(module);
448 PyObject_SetAttrString(result,
"__module__", modstr);
451 nassertr(PyType_Check(result),
nullptr);
452 return (PyTypeObject *)result;
458 PyObject *DTool_CreatePyInstanceTyped(
void *local_this_in, Dtool_PyTypedObject &known_class_type,
bool memory_rules,
bool is_const,
int type_index) {
463 nassertr(local_this_in !=
nullptr,
nullptr);
466 if (type_index > 0) {
468 Dtool_PyTypedObject *target_class = (Dtool_PyTypedObject *)TypeHandle::from_index(type_index).get_python_type();
469 if (target_class !=
nullptr) {
471 void *new_local_this = target_class->_Dtool_DowncastInterface(local_this_in, &known_class_type);
472 if (new_local_this !=
nullptr) {
474 Dtool_PyInstDef *
self = (Dtool_PyInstDef *) target_class->_PyType.tp_new(&target_class->_PyType,
nullptr,
nullptr);
475 if (
self !=
nullptr) {
476 self->_ptr_to_object = new_local_this;
477 self->_memory_rules = memory_rules;
478 self->_is_const = is_const;
480 self->_My_Type = target_class;
481 return (PyObject *)
self;
489 Dtool_PyInstDef *
self = (Dtool_PyInstDef *) known_class_type._PyType.tp_new(&known_class_type._PyType,
nullptr,
nullptr);
490 if (
self !=
nullptr) {
491 self->_ptr_to_object = local_this_in;
492 self->_memory_rules = memory_rules;
493 self->_is_const = is_const;
495 self->_My_Type = &known_class_type;
497 return (PyObject *)
self;
502 PyObject *
DTool_CreatePyInstance(
void *local_this, Dtool_PyTypedObject &in_classdef,
bool memory_rules,
bool is_const) {
503 if (local_this ==
nullptr) {
510 Dtool_PyTypedObject *classdef = &in_classdef;
511 Dtool_PyInstDef *
self = (Dtool_PyInstDef *) classdef->_PyType.tp_new(&classdef->_PyType,
nullptr,
nullptr);
512 if (
self !=
nullptr) {
513 self->_ptr_to_object = local_this;
514 self->_memory_rules = memory_rules;
515 self->_is_const = is_const;
516 self->_My_Type = classdef;
518 return (PyObject *)
self;
524 Dtool_TypeMap *Dtool_GetGlobalTypeMap() {
525 PyObject *capsule = PySys_GetObject((
char *)
"_interrogate_types");
526 if (capsule !=
nullptr) {
527 return (Dtool_TypeMap *)PyCapsule_GetPointer(capsule,
nullptr);
529 Dtool_TypeMap *type_map =
new Dtool_TypeMap;
530 capsule = PyCapsule_New((
void *)type_map,
nullptr,
nullptr);
531 PySys_SetObject((
char *)
"_interrogate_types", capsule);
537 #define PY_MAJOR_VERSION_STR #PY_MAJOR_VERSION "." #PY_MINOR_VERSION
539 #if PY_MAJOR_VERSION >= 3
540 PyObject *Dtool_PyModuleInitHelper(
const LibraryDef *defs[], PyModuleDef *module_def) {
542 PyObject *Dtool_PyModuleInitHelper(
const LibraryDef *defs[],
const char *modulename) {
545 string version = Py_GetVersion();
546 size_t version_len = version.find(
'.', 2);
547 if (version_len != string::npos) {
548 version.resize(version_len);
551 if (version != STRINGIFY_VERSION(PY_MAJOR_VERSION, PY_MINOR_VERSION)) {
554 std::ostringstream errs;
555 errs <<
"this module was compiled for Python "
556 << PY_MAJOR_VERSION <<
"." << PY_MINOR_VERSION <<
", which is "
557 <<
"incompatible with Python " << version;
558 string error = errs.str();
559 PyErr_SetString(PyExc_ImportError, error.c_str());
563 Dtool_TypeMap *type_map = Dtool_GetGlobalTypeMap();
566 MethodDefmap functions;
567 for (
size_t i = 0; defs[i] !=
nullptr; i++) {
568 const LibraryDef &def = *defs[i];
571 for (PyMethodDef *meth = def._methods; meth->ml_name !=
nullptr; meth++) {
572 if (functions.find(meth->ml_name) == functions.end()) {
573 functions[meth->ml_name] = meth;
578 const Dtool_TypeDef *types = def._types;
579 if (types !=
nullptr) {
580 while (types->name !=
nullptr) {
581 (*type_map)[std::string(types->name)] = types->type;
588 for (
size_t i = 0; defs[i] !=
nullptr; i++) {
589 const LibraryDef &def = *defs[i];
591 Dtool_TypeDef *types = def._external_types;
592 if (types !=
nullptr) {
593 while (types->name !=
nullptr) {
594 auto it = type_map->find(std::string(types->name));
595 if (it != type_map->end()) {
596 types->type = it->second;
598 return PyErr_Format(PyExc_NameError,
"name '%s' is not defined", types->name);
605 PyMethodDef *newdef =
new PyMethodDef[functions.size() + 1];
606 MethodDefmap::iterator mi;
608 for (mi = functions.begin(); mi != functions.end(); mi++, offset++) {
609 newdef[offset] = *mi->second;
611 newdef[offset].ml_doc =
nullptr;
612 newdef[offset].ml_name =
nullptr;
613 newdef[offset].ml_meth =
nullptr;
614 newdef[offset].ml_flags = 0;
616 #if PY_MAJOR_VERSION >= 3
617 module_def->m_methods = newdef;
618 PyObject *module = PyModule_Create(module_def);
620 PyObject *module = Py_InitModule((
char *)modulename, newdef);
623 if (module ==
nullptr) {
624 #if PY_MAJOR_VERSION >= 3
625 return Dtool_Raise_TypeError(
"PyModule_Create returned NULL");
627 return Dtool_Raise_TypeError(
"Py_InitModule returned NULL");
633 static bool initialized_main_dir =
false;
634 if (!initialized_main_dir) {
635 if (interrogatedb_cat.is_debug()) {
637 interrogatedb_cat.debug()
638 <<
"Python " << version <<
"\n";
643 PyObject *main_module = PyImport_ImportModule(
"__main__");
644 if (main_module == NULL) {
645 interrogatedb_cat.warning() <<
"Unable to import __main__\n";
650 PyObject *file_attr =
nullptr;
651 if (main_module !=
nullptr) {
652 file_attr = PyObject_GetAttrString(main_module,
"__file__");
654 if (file_attr ==
nullptr) {
658 #if PY_MAJOR_VERSION >= 3
660 wchar_t *buffer = PyUnicode_AsWideCharString(file_attr, &length);
661 if (buffer !=
nullptr) {
670 if (PyString_AsStringAndSize(file_attr, &buffer, &length) != -1) {
677 interrogatedb_cat.warning() <<
"Invalid string for __main__.__file__\n";
683 initialized_main_dir =
true;
686 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
687 global_thread_state_swap = PyThreadState_Swap;
691 PyModule_AddIntConstant(module,
"Dtool_PyNativeInterface", 1);
698 PyObject *Dtool_BorrowThisReference(PyObject *
self, PyObject *args) {
699 PyObject *from_in =
nullptr;
700 PyObject *to_in =
nullptr;
701 if (PyArg_UnpackTuple(args,
"Dtool_BorrowThisReference", 2, 2, &to_in, &from_in)) {
703 if (DtoolInstance_Check(from_in) && DtoolInstance_Check(to_in)) {
704 Dtool_PyInstDef *from = (Dtool_PyInstDef *) from_in;
705 Dtool_PyInstDef *to = (Dtool_PyInstDef *) to_in;
708 if (from->_My_Type == to->_My_Type) {
709 to->_memory_rules =
false;
710 to->_is_const = from->_is_const;
711 to->_ptr_to_object = from->_ptr_to_object;
717 return PyErr_Format(PyExc_TypeError,
"types %s and %s do not match",
718 Py_TYPE(from)->tp_name, Py_TYPE(to)->tp_name);
720 return Dtool_Raise_TypeError(
"One of these does not appear to be DTOOL Instance ??");
728 EXPCL_PYPANDA PyObject *
729 Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
733 if (PyArg_ParseTuple(args,
"OSO", &
self, &key, &subject)) {
734 PyObject *dict = ((PyTypeObject *)
self)->tp_dict;
735 if (dict ==
nullptr || !PyDict_Check(dict)) {
736 return Dtool_Raise_TypeError(
"No dictionary On Object");
738 PyDict_SetItem(dict, key, subject);
741 if (PyErr_Occurred()) {
752 PyObject *copy_from_make_copy(PyObject *
self, PyObject *noargs) {
753 PyObject *callable = PyObject_GetAttrString(
self,
"make_copy");
754 if (callable ==
nullptr) {
757 PyObject *result = _PyObject_CallNoArg(callable);
766 PyObject *copy_from_copy_constructor(PyObject *
self, PyObject *noargs) {
767 PyObject *callable = (PyObject *)Py_TYPE(
self);
768 return _PyObject_FastCall(callable, &
self, 1);
776 PyObject *map_deepcopy_to_copy(PyObject *
self, PyObject *args) {
777 PyObject *callable = PyObject_GetAttrString(
self,
"__copy__");
778 if (callable ==
nullptr) {
781 PyObject *result = _PyObject_CallNoArg(callable);
790 bool Dtool_ExtractArg(PyObject **result, PyObject *args, PyObject *kwds,
791 const char *keyword) {
793 if (PyTuple_GET_SIZE(args) == 1) {
794 if (kwds ==
nullptr || PyDict_GET_SIZE(kwds) == 0) {
795 *result = PyTuple_GET_ITEM(args, 0);
798 }
else if (PyTuple_GET_SIZE(args) == 0) {
801 if (kwds !=
nullptr && PyDict_GET_SIZE(kwds) == 1 &&
802 PyDict_Next(kwds, &ppos, &key, result)) {
804 #if PY_VERSION_HEX >= 0x03060000
805 return PyUnicode_CheckExact(key) && _PyUnicode_EqualToASCIIString(key, keyword);
806 #elif PY_MAJOR_VERSION >= 3
807 return PyUnicode_CheckExact(key) && PyUnicode_CompareWithASCIIString(key, keyword) == 0;
809 return PyString_CheckExact(key) && strcmp(PyString_AS_STRING(key), keyword) == 0;
820 bool Dtool_ExtractArg(PyObject **result, PyObject *args, PyObject *kwds) {
821 if (PyTuple_GET_SIZE(args) == 1 &&
822 (kwds ==
nullptr || PyDict_GET_SIZE(kwds) == 0)) {
823 *result = PyTuple_GET_ITEM(args, 0);
836 bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds,
837 const char *keyword) {
839 if (PyTuple_GET_SIZE(args) == 1) {
840 if (kwds ==
nullptr || PyDict_GET_SIZE(kwds) == 0) {
841 *result = PyTuple_GET_ITEM(args, 0);
844 }
else if (PyTuple_GET_SIZE(args) == 0) {
845 if (kwds !=
nullptr && PyDict_GET_SIZE(kwds) == 1) {
848 if (!PyDict_Next(kwds, &ppos, &key, result)) {
853 #if PY_VERSION_HEX >= 0x03060000
854 return PyUnicode_CheckExact(key) && _PyUnicode_EqualToASCIIString(key, keyword);
855 #elif PY_MAJOR_VERSION >= 3
856 return PyUnicode_CheckExact(key) && PyUnicode_CompareWithASCIIString(key, keyword) == 0;
858 return PyString_CheckExact(key) && strcmp(PyString_AS_STRING(key), keyword) == 0;
871 bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds) {
872 if (kwds !=
nullptr && PyDict_GET_SIZE(kwds) != 0) {
875 if (PyTuple_GET_SIZE(args) == 1) {
876 *result = PyTuple_GET_ITEM(args, 0);
879 return (PyTuple_GET_SIZE(args) == 0);
static void shadow_environment_variable(const std::string &var, const std::string &value)
Changes the apparent definition of the indicated environment variable by masking it within this class...
has_environment_variable
Returns true if the indicated environment variable is defined.
get_cwd
Returns the name of the current working directory.
The name of a file, such as a texture file or an Egg file.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
static Filename from_os_specific_w(const std::wstring &os_specific, Type type=T_general)
The wide-string variant of from_os_specific().
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
std::string get_dirname() const
Returns the directory part of the filename.
void make_absolute()
Converts the filename to a fully-qualified pathname from the root (if it is a relative pathname),...
An object that handles general error reporting to the user.
const std::string & get_assert_error_message() const
Returns the error message that corresponds to the assertion that most recently failed.
void clear_assert_failed()
Resets the assert_failed flag that is set whenever an assertion test fails.
static Notify * ptr()
Returns the pointer to the global Notify object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PyObject * DTool_CreatePyInstance(const T *obj, bool memory_rules)
These functions wrap a pointer for a class that defines get_type_handle().