소스 검색

interrogate: clean py_panda.h; use macros to access Dtool_PyInstDef

rdb 8 년 전
부모
커밋
193e4b5f59

+ 1 - 1
dtool/src/dtoolutil/filename_ext.cxx

@@ -55,7 +55,7 @@ __init__(PyObject *path) {
 
   if (Py_TYPE(path) == &Dtool_Filename._PyType) {
     // Copy constructor.
-    (*_this) = *((Filename *)((Dtool_PyInstDef *)path)->_ptr_to_object);
+    *_this = *(Filename *)DtoolInstance_VOID_PTR(path);
     return;
   }
 

+ 27 - 29
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -1094,14 +1094,14 @@ write_class_details(ostream &out, Object *obj) {
   // Write support methods to cast from and to pointers of this type.
   {
     out << "static void *Dtool_UpcastInterface_" << ClassName << "(PyObject *self, Dtool_PyTypedObject *requested_type) {\n";
-    out << "  Dtool_PyTypedObject *SelfType = ((Dtool_PyInstDef *)self)->_My_Type;\n";
-    out << "  if (SelfType != Dtool_Ptr_" << ClassName << ") {\n";
+    out << "  Dtool_PyTypedObject *type = DtoolInstance_TYPE(self);\n";
+    out << "  if (type != &Dtool_" << ClassName << ") {\n";
     out << "    printf(\"" << ClassName << " ** Bad Source Type-- Requesting Conversion from %s to %s\\n\", Py_TYPE(self)->tp_name, requested_type->_PyType.tp_name); fflush(NULL);\n";;
     out << "    return NULL;\n";
     out << "  }\n";
     out << "\n";
-    out << "  " << cClassName << " *local_this = (" << cClassName << " *)((Dtool_PyInstDef *)self)->_ptr_to_object;\n";
-    out << "  if (requested_type == Dtool_Ptr_" << ClassName << ") {\n";
+    out << "  " << cClassName << " *local_this = (" << cClassName << " *)DtoolInstance_VOID_PTR(self);\n";
+    out << "  if (requested_type == &Dtool_" << ClassName << ") {\n";
     out << "    return local_this;\n";
     out << "  }\n";
 
@@ -2220,13 +2220,13 @@ write_module_class(ostream &out, Object *obj) {
           // provide a writable buffer or a readonly buffer.
           const string const_this = "(const " + cClassName + " *)local_this";
           if (remap_const != NULL && remap_nonconst != NULL) {
-            out << "  if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+            out << "  if (!DtoolInstance_IS_CONST(self)) {\n";
             out << "    return " << remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst) << ";\n";
             out << "  } else {\n";
             out << "    return " << remap_const->call_function(out, 4, false, const_this, params_const) << ";\n";
             out << "  }\n";
           } else if (remap_nonconst != NULL) {
-            out << "  if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+            out << "  if (!DtoolInstance_IS_CONST(self)) {\n";
             out << "    return " << remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst) << ";\n";
             out << "  } else {\n";
             out << "    Dtool_Raise_TypeError(\"Cannot call " << ClassName << ".__getbuffer__() on a const object.\");\n";
@@ -2285,7 +2285,7 @@ write_module_class(ostream &out, Object *obj) {
           string return_expr;
           const string const_this = "(const " + cClassName + " *)local_this";
           if (remap_const != NULL && remap_nonconst != NULL) {
-            out << "  if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+            out << "  if (!DtoolInstance_IS_CONST(self)) {\n";
             return_expr = remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst);
             if (!return_expr.empty()) {
               out << "    " << return_expr << ";\n";
@@ -3078,7 +3078,7 @@ write_module_class(ostream &out, Object *obj) {
 
     out << "    Dtool_" << ClassName << "._PyType.tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n";
   } else {
-    out << "    Dtool_" << ClassName << "._PyType.tp_base = (PyTypeObject *)Dtool_Ptr_DTOOL_SUPER_BASE;\n";
+    out << "    Dtool_" << ClassName << "._PyType.tp_base = (PyTypeObject *)&Dtool_DTOOL_SUPER_BASE;\n";
   }
 
   int num_nested = obj->_itype.number_of_nested_types();
@@ -3515,8 +3515,9 @@ write_function_for_name(ostream &out, Object *obj,
       out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", "
           << "(void **)&local_this, \"" << classNameFromCppName(cClassName, false)
           << "." << methodNameFromCppName(remap, cClassName, false) << "\")) {\n";
+
     } else {
-      out << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
+      out << "  if (!DtoolInstance_GetPointer(self, local_this, Dtool_" << ClassName << ")) {\n";
     }
 
     error_return(out, 4, return_flags);
@@ -3616,7 +3617,7 @@ write_function_for_name(ostream &out, Object *obj,
       if (strip_keyword_args) {
         // None of the remaps take any keyword arguments, so let's check that
         // we take none.  This saves some checks later on.
-        indent(out, 4) << "if (kwds == NULL || ((PyDictObject *)kwds)->ma_used == 0) {\n";
+        indent(out, 4) << "if (kwds == NULL || PyDict_GET_SIZE(kwds) == 0) {\n";
         if (min_args == 1 && min_args == 1) {
           indent(out, 4) << "  PyObject *arg = PyTuple_GET_ITEM(args, 0);\n";
           write_function_forset(out, mii->second, min_args, max_args, expected_params, 6,
@@ -3890,11 +3891,10 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) {
     // Note: this relies on the PT() being initialized to NULL.  This is
     // currently the case in all invocations, but this may not be true in the
     // future.
-    out << "  DTOOL_Call_ExtractThisPointerForType(args, &Dtool_" << ClassName << ", (void**)&coerced.cheat());\n";
-    out << "  if (coerced != NULL) {\n";
+    out << "  if (DtoolInstance_GetPointer(args, coerced.cheat(), Dtool_" << ClassName << ")) {\n";
     out << "    // The argument is already of matching type, no need to coerce.\n";
     if (!is_const) {
-      out << "    if (!((Dtool_PyInstDef *)args)->_is_const) {\n";
+      out << "    if (!DtoolInstance_IS_CONST(args)) {\n";
       out << "      // A non-const instance is required, which this is.\n";
       out << "      coerced->ref();\n";
       out << "      return true;\n";
@@ -3909,9 +3909,8 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) {
     out << cClassName << " *Dtool_Coerce_" << ClassName << "(PyObject *args, " << cClassName << " &coerced) {\n";
 
     out << "  " << cClassName << " *local_this;\n";
-    out << "  DTOOL_Call_ExtractThisPointerForType(args, &Dtool_" << ClassName << ", (void**)&local_this);\n";
-    out << "  if (local_this != NULL) {\n";
-    out << "    if (((Dtool_PyInstDef *)args)->_is_const) {\n";
+    out << "  if (DtoolInstance_GetPointer(args, local_this, Dtool_" << ClassName << ")) {\n";
+    out << "    if (DtoolInstance_IS_CONST(args)) {\n";
     out << "      // This is a const object.  Make a copy.\n";
     out << "      coerced = *(const " << cClassName << " *)local_this;\n";
     out << "      return &coerced;\n";
@@ -4340,7 +4339,7 @@ write_function_forset(ostream &out,
     if (all_nonconst) {
       // Yes, they do.  Check that the parameter has the required constness.
       indent(out, indent_level)
-        << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+        << "if (!DtoolInstance_IS_CONST(self)) {\n";
       indent_level += 2;
       verify_const = false;
     }
@@ -4406,7 +4405,7 @@ write_function_forset(ostream &out,
       if (verify_const && (remap->_has_this && !remap->_const_method)) {
         // If it's a non-const method, we only allow a non-const this.
         indent(out, indent_level)
-          << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+          << "if (!DtoolInstance_IS_CONST(self)) {\n";
       } else {
         indent(out, indent_level)
           << "{\n";
@@ -4441,7 +4440,7 @@ write_function_forset(ostream &out,
 
         if (verify_const && (remap->_has_this && !remap->_const_method)) {
           indent(out, indent_level)
-            << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+            << "if (!DtoolInstance_IS_CONST(self)) {\n";
         } else {
           indent(out, indent_level)
             << "{\n";
@@ -5525,14 +5524,13 @@ write_function_instance(ostream &out, FunctionRemap *remap,
           // This function does the same thing in this case and is slightly
           // simpler.  But maybe we should just reorganize these functions
           // entirely?
-          extra_convert << ";\n";
-          if (is_optional) {
-            extra_convert << "  ";
-          }
-          extra_convert
-            << "DTOOL_Call_ExtractThisPointerForType(" << param_name
-            << ", Dtool_Ptr_" << make_safe_name(class_name)
-            << ", (void **)&" << param_name << "_this);\n";
+          extra_convert << " = NULL;\n";
+          int indent_level = is_optional ? 2 : 0;
+          indent(extra_convert, indent_level)
+            << "DtoolInstance_GetPointer(" << param_name
+            << ", " << param_name << "_this"
+            << ", *Dtool_Ptr_" << make_safe_name(class_name)
+            << ");\n";
         } else {
           extra_convert << boolalpha
             << " = (" << class_name << " *)"
@@ -6796,7 +6794,7 @@ write_getset(ostream &out, Object *obj, Property *property) {
     out << "  if (wrap != NULL) {\n"
            "    wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getitem;\n";
     if (!property->_setter_remaps.empty()) {
-      out << "    if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+      out << "    if (!DtoolInstance_IS_CONST(self)) {\n";
       out << "      wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Setitem;\n";
       out << "    }\n";
     }
@@ -6828,7 +6826,7 @@ write_getset(ostream &out, Object *obj, Property *property) {
         "    wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
         "    wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n";
       if (!property->_setter_remaps.empty()) {
-        out << "    if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
+        out << "    if (!DtoolInstance_IS_CONST(self)) {\n";
         out << "      wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Setitem;\n";
         if (property->_inserter != nullptr) {
           out << "      wrap->_insert_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_insert;\n";

+ 6 - 0
dtool/src/interrogatedb/py_compat.h

@@ -155,6 +155,12 @@ extern EXPCL_INTERROGATEDB PyTupleObject Dtool_EmptyTuple;
 #  define PyLong_AsLongLongAndOverflow(x) PyLong_AsLongAndOverflow(x)
 #endif
 
+/* Python 3.7 */
+
+#ifndef PyDict_GET_SIZE
+#  define PyDict_GET_SIZE(mp) (((PyDictObject *)mp)->ma_used)
+#endif
+
 /* Other Python implementations */
 
 // _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.

+ 41 - 7
dtool/src/interrogatedb/py_panda.I

@@ -11,20 +11,54 @@
  * @date 2016-06-06
  */
 
+#ifdef _MSC_VER
+#define _IS_FINAL(T) (__is_sealed(T))
+#elif defined(__GNUC__)
+#define _IS_FINAL(T) (__is_final(T))
+#else
+#define _IS_FINAL(T) (0)
+#endif
+
 /**
  * Template function that can be used to extract any TypedObject pointer from
  * a wrapped Python object.
  */
 template<class T> INLINE bool
-DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) {
-  if (DtoolCanThisBeAPandaInstance(self)) {
+DtoolInstance_GetPointer(PyObject *self, T *&into) {
+  if (DtoolInstance_Check(self)) {
     Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
-    if (target_class != NULL) {
-      into = (T*) ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, target_class);
-      return (into != NULL);
+    if (target_class != nullptr) {
+      if (_IS_FINAL(T)) {
+        if (DtoolInstance_TYPE(self) == target_class) {
+          into = (T *)DtoolInstance_VOID_PTR(self);
+        }
+      } else {
+        into = (T *)DtoolInstance_UPCAST(self, *target_class);
+      }
+      return (into != nullptr);
+    }
+  }
+  into = nullptr;
+  return false;
+}
+
+/**
+ * Template function that can be used to extract any TypedObject pointer from
+ * a wrapped Python object.  In this case, the Dtool_PyTypedObject is known.
+ */
+template<class T> INLINE bool
+DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &target_class) {
+  if (DtoolInstance_Check(self)) {
+    if (_IS_FINAL(T)) {
+      if (DtoolInstance_TYPE(self) == &target_class) {
+        into = (T *)DtoolInstance_VOID_PTR(self);
+      }
+    } else {
+      into = (T *)DtoolInstance_UPCAST(self, target_class);
     }
+    return (into != nullptr);
   }
-  into = NULL;
+  into = nullptr;
   return false;
 }
 
@@ -73,7 +107,7 @@ Dtool_CheckNoArgs(PyObject *args) {
 ALWAYS_INLINE bool
 Dtool_CheckNoArgs(PyObject *args, PyObject *kwds) {
   return PyTuple_GET_SIZE(args) == 0 &&
-    (kwds == NULL || ((PyDictObject *)kwds)->ma_used == 0);
+    (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0);
 }
 
 /**

+ 30 - 54
dtool/src/interrogatedb/py_panda.cxx

@@ -31,34 +31,14 @@ static RuntimeTypeMap runtime_type_map;
 static RuntimeTypeSet runtime_type_set;
 static NamedTypeMap named_type_map;
 
-
-/**
- * Given a valid (non-NULL) PyObject, does a simple check to see if it might
- * be an instance of a Panda type.  It does this using a signature that is
- * encoded on each instance.
- */
-bool DtoolCanThisBeAPandaInstance(PyObject *self) {
-  // simple sanity check for the class type..size.. will stop basic foobars..
-  // It is arguably better to use something like this:
-  // PyType_IsSubtype(Py_TYPE(self), &Dtool_DTOOL_SUPER_BASE._PyType) ...but
-  // probably not as fast.
-  if (Py_TYPE(self)->tp_basicsize >= (int)sizeof(Dtool_PyInstDef)) {
-    Dtool_PyInstDef *pyself = (Dtool_PyInstDef *) self;
-    if (pyself->_signature == PY_PANDA_SIGNATURE) {
-      return true;
-    }
-  }
-  return false;
-}
-
 /**
 
  */
 void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer) {
-  if (DtoolCanThisBeAPandaInstance(self)) {
-    *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, classdef);
+  if (DtoolInstance_Check(self)) {
+    *answer = DtoolInstance_UPCAST(self, *classdef);
   } else {
-    *answer = NULL;
+    *answer = nullptr;
   }
 }
 
@@ -68,12 +48,12 @@ void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *c
  * was of the wrong type, raises an AttributeError.
  */
 bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer) {
-  if (self == NULL || !DtoolCanThisBeAPandaInstance(self) || ((Dtool_PyInstDef *)self)->_ptr_to_object == NULL) {
+  if (self == nullptr || !DtoolInstance_Check(self) || DtoolInstance_VOID_PTR(self) == nullptr) {
     Dtool_Raise_TypeError("C++ object is not yet constructed, or already destructed.");
     return false;
   }
 
-  *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
+  *answer = DtoolInstance_UPCAST(self, classdef);
   return true;
 }
 
@@ -88,12 +68,12 @@ bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef
 bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
                                             void **answer, const char *method_name) {
 
-  if (self == NULL || !DtoolCanThisBeAPandaInstance(self) || ((Dtool_PyInstDef *)self)->_ptr_to_object == NULL) {
+  if (self == nullptr || !DtoolInstance_Check(self) || DtoolInstance_VOID_PTR(self) == nullptr) {
     Dtool_Raise_TypeError("C++ object is not yet constructed, or already destructed.");
     return false;
   }
 
-  if (((Dtool_PyInstDef *)self)->_is_const) {
+  if (DtoolInstance_IS_CONST(self)) {
     // All overloads of this function are non-const.
     PyErr_Format(PyExc_TypeError,
                  "Cannot call %s() on a const object.",
@@ -101,7 +81,7 @@ bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject
     return false;
   }
 
-  *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
+  *answer = DtoolInstance_UPCAST(self, classdef);
   return true;
 }
 
@@ -131,19 +111,19 @@ void *
 DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
                                int param, const string &function_name, bool const_ok,
                                bool report_errors) {
-  // if (PyErr_Occurred()) { return NULL; }
-  if (self == NULL) {
+  // if (PyErr_Occurred()) { return nullptr; }
+  if (self == nullptr) {
     if (report_errors) {
-      return Dtool_Raise_TypeError("self is NULL");
+      return Dtool_Raise_TypeError("self is nullptr");
     }
-    return NULL;
+    return nullptr;
   }
 
-  if (DtoolCanThisBeAPandaInstance(self)) {
-    void *result = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, classdef);
+  if (DtoolInstance_Check(self)) {
+    void *result = DtoolInstance_UPCAST(self, *classdef);
 
-    if (result != NULL) {
-      if (const_ok || !((Dtool_PyInstDef *)self)->_is_const) {
+    if (result != nullptr) {
+      if (const_ok || !DtoolInstance_IS_CONST(self)) {
         return result;
       }
 
@@ -152,7 +132,7 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
                             "%s() argument %d may not be const",
                             function_name.c_str(), param);
       }
-      return NULL;
+      return nullptr;
     }
   }
 
@@ -160,17 +140,14 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
     return Dtool_Raise_ArgTypeError(self, param, function_name.c_str(), classdef->_PyType.tp_name);
   }
 
-  return NULL;
+  return nullptr;
 }
 
 void *DTOOL_Call_GetPointerThis(PyObject *self) {
-  if (self != NULL) {
-    if (DtoolCanThisBeAPandaInstance(self)) {
-      Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self;
-      return pyself->_ptr_to_object;
-    }
+  if (self != nullptr && DtoolInstance_Check(self)) {
+    return DtoolInstance_VOID_PTR(self);
   }
-  return NULL;
+  return nullptr;
 }
 
 /**
@@ -713,7 +690,7 @@ PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) {
   PyObject *to_in = NULL;
   if (PyArg_UnpackTuple(args, "Dtool_BorrowThisReference", 2, 2, &to_in, &from_in)) {
 
-    if (DtoolCanThisBeAPandaInstance(from_in) && DtoolCanThisBeAPandaInstance(to_in)) {
+    if (DtoolInstance_Check(from_in) && DtoolInstance_Check(to_in)) {
       Dtool_PyInstDef *from = (Dtool_PyInstDef *) from_in;
       Dtool_PyInstDef *to = (Dtool_PyInstDef *) to_in;
 
@@ -758,9 +735,8 @@ PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
 }
 
 Py_hash_t DTOOL_PyObject_HashPointer(PyObject *self) {
-  if (self != NULL && DtoolCanThisBeAPandaInstance(self)) {
-    Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self;
-    return (Py_hash_t) pyself->_ptr_to_object;
+  if (self != nullptr && DtoolInstance_Check(self)) {
+    return (Py_hash_t)DtoolInstance_VOID_PTR(self);
   }
   return -1;
 }
@@ -933,14 +909,14 @@ bool Dtool_ExtractArg(PyObject **result, PyObject *args, PyObject *kwds,
                       const char *keyword) {
 
   if (PyTuple_GET_SIZE(args) == 1) {
-    if (kwds == NULL || ((PyDictObject *)kwds)->ma_used == 0) {
+    if (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0) {
       *result = PyTuple_GET_ITEM(args, 0);
       return true;
     }
   } else if (PyTuple_GET_SIZE(args) == 0) {
     PyObject *key;
     Py_ssize_t ppos = 0;
-    if (kwds != NULL && ((PyDictObject *)kwds)->ma_used == 1 &&
+    if (kwds != nullptr && PyDict_GET_SIZE(kwds) == 1 &&
         PyDict_Next(kwds, &ppos, &key, result)) {
       // We got the item, we just need to make sure that it had the right key.
 #if PY_VERSION_HEX >= 0x03060000
@@ -961,7 +937,7 @@ bool Dtool_ExtractArg(PyObject **result, PyObject *args, PyObject *kwds,
  */
 bool Dtool_ExtractArg(PyObject **result, PyObject *args, PyObject *kwds) {
   if (PyTuple_GET_SIZE(args) == 1 &&
-      (kwds == NULL || ((PyDictObject *)kwds)->ma_used == 0)) {
+      (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0)) {
     *result = PyTuple_GET_ITEM(args, 0);
     return true;
   }
@@ -979,12 +955,12 @@ bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds,
                               const char *keyword) {
 
   if (PyTuple_GET_SIZE(args) == 1) {
-    if (kwds == NULL || ((PyDictObject *)kwds)->ma_used == 0) {
+    if (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0) {
       *result = PyTuple_GET_ITEM(args, 0);
       return true;
     }
   } else if (PyTuple_GET_SIZE(args) == 0) {
-    if (kwds != NULL && ((PyDictObject *)kwds)->ma_used == 1) {
+    if (kwds != nullptr && PyDict_GET_SIZE(kwds) == 1) {
       PyObject *key;
       Py_ssize_t ppos = 0;
       if (!PyDict_Next(kwds, &ppos, &key, result)) {
@@ -1011,7 +987,7 @@ bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds,
  * Variant of Dtool_ExtractOptionalArg that does not accept a keyword argument.
  */
 bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds) {
-  if (kwds != NULL && ((PyDictObject *)kwds)->ma_used != 0) {
+  if (kwds != nullptr && PyDict_GET_SIZE(kwds) != 0) {
     return false;
   }
   if (PyTuple_GET_SIZE(args) == 1) {

+ 21 - 18
dtool/src/interrogatedb/py_panda.h

@@ -127,7 +127,7 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
 #else // NDEBUG
 #define Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\
 static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
-  if (((Dtool_PyInstDef *)self)->_ptr_to_object != NULL) {\
+  if (DtoolInstance_VOID_PTR(self) != nullptr) {\
     if (((Dtool_PyInstDef *)self)->_memory_rules) {\
       cerr << "Detected leak for " << #CLASS_NAME \
            << " which interrogate cannot delete.\n"; \
@@ -139,9 +139,9 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
 
 #define Define_Dtool_FreeInstance(CLASS_NAME,CNAME)\
 static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
-  if (((Dtool_PyInstDef *)self)->_ptr_to_object != NULL) {\
+  if (DtoolInstance_VOID_PTR(self) != nullptr) {\
     if (((Dtool_PyInstDef *)self)->_memory_rules) {\
-      delete ((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\
+      delete (CNAME *)DtoolInstance_VOID_PTR(self);\
     }\
   }\
   Py_TYPE(self)->tp_free(self);\
@@ -149,9 +149,9 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
 
 #define Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\
 static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
-  if (((Dtool_PyInstDef *)self)->_ptr_to_object != NULL) {\
+  if (DtoolInstance_VOID_PTR(self) != nullptr) {\
     if (((Dtool_PyInstDef *)self)->_memory_rules) {\
-      unref_delete((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\
+      unref_delete((CNAME *)DtoolInstance_VOID_PTR(self));\
     }\
   }\
   Py_TYPE(self)->tp_free(self);\
@@ -163,8 +163,17 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
   Py_TYPE(self)->tp_free(self);\
 }
 
-// Simple Recognition Functions..
-EXPCL_INTERROGATEDB bool DtoolCanThisBeAPandaInstance(PyObject *self);
+// Use DtoolInstance_Check to check whether a PyObject* is a DtoolInstance.
+#define DtoolInstance_Check(obj) \
+  (Py_TYPE(obj)->tp_basicsize >= (int)sizeof(Dtool_PyInstDef) && \
+   ((Dtool_PyInstDef *)obj)->_signature == PY_PANDA_SIGNATURE)
+
+// These macros access the DtoolInstance without error checking.
+#define DtoolInstance_TYPE(obj) (((Dtool_PyInstDef *)obj)->_My_Type)
+#define DtoolInstance_IS_CONST(obj) (((Dtool_PyInstDef *)obj)->_is_const)
+#define DtoolInstance_VOID_PTR(obj) (((Dtool_PyInstDef *)obj)->_ptr_to_object)
+#define DtoolInstance_INIT_PTR(obj, ptr) { ((Dtool_PyInstDef *)obj)->_ptr_to_object = (void*)(ptr); }
+#define DtoolInstance_UPCAST(obj, type) (((Dtool_PyInstDef *)(obj))->_My_Type->_Dtool_UpcastInterface((obj), &(type)))
 
 // ** HACK ** allert.. Need to keep a runtime type dictionary ... that is
 // forward declared of typed object.  We rely on the fact that typed objects
@@ -192,20 +201,14 @@ EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyT
 EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
                                                               void **answer, const char *method_name);
 
-template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into);
+template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into);
+template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &classdef);
 
 // Functions related to error reporting.
 EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred();
 
-// _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.
-// Some implementations of the CPython API (e.g. PyPy's cpyext) do not define
-// it, so in these cases we just silently fall back to PyErr_Occurred.
-#ifndef _PyErr_OCCURRED
-#define _PyErr_OCCURRED() PyErr_Occurred()
-#endif
-
 #ifdef NDEBUG
-#define Dtool_CheckErrorOccurred() (UNLIKELY(_PyErr_OCCURRED() != NULL))
+#define Dtool_CheckErrorOccurred() (UNLIKELY(_PyErr_OCCURRED() != nullptr))
 #else
 #define Dtool_CheckErrorOccurred() (UNLIKELY(_Dtool_CheckErrorOccurred()))
 #endif
@@ -232,8 +235,8 @@ EXPCL_INTERROGATEDB PyObject *Dtool_Return_Bool(bool value);
 EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value);
 
 #ifdef NDEBUG
-#define Dtool_Return_None() (_PyErr_OCCURRED() != NULL ? NULL : (Py_INCREF(Py_None), Py_None))
-#define Dtool_Return(value) (_PyErr_OCCURRED() != NULL ? NULL : value)
+#define Dtool_Return_None() (LIKELY(_PyErr_OCCURRED() == nullptr) ? (Py_INCREF(Py_None), Py_None) : nullptr)
+#define Dtool_Return(value) (LIKELY(_PyErr_OCCURRED() == nullptr) ? value : nullptr)
 #else
 #define Dtool_Return_None() _Dtool_Return_None()
 #define Dtool_Return(value) _Dtool_Return(value)

+ 3 - 4
panda/src/event/pythonTask.cxx

@@ -583,12 +583,11 @@ do_python_task() {
         return DS_done;
       }
 
-    } else if (DtoolCanThisBeAPandaInstance(result)) {
+    } else if (DtoolInstance_Check(result)) {
       // We are waiting for an AsyncFuture (eg. other task) to finish.
-      void *ptr = ((Dtool_PyInstDef *)result)->_My_Type->_Dtool_UpcastInterface(result, &Dtool_AsyncFuture);
-      if (ptr != nullptr) {
+      AsyncFuture *fut = (AsyncFuture *)DtoolInstance_UPCAST(result, Dtool_AsyncFuture);
+      if (fut != nullptr) {
         // Suspend execution of this task until this other task has completed.
-        AsyncFuture *fut = (AsyncFuture *)ptr;
         AsyncTaskManager *manager = fut->_manager;
         if (manager == nullptr) {
           manager = _manager;

+ 2 - 2
panda/src/express/pointerToArray_ext.I

@@ -97,7 +97,7 @@ __init__(PyObject *self, PyObject *source) {
 
   // Now construct the internal list by copying the elements one-at-a-time
   // from Python.
-  PyObject *dict = ((Dtool_PyInstDef *)self)->_My_Type->_PyType.tp_dict;
+  PyObject *dict = DtoolInstance_TYPE(self)->_PyType.tp_dict;
   PyObject *push_back = PyDict_GetItemString(dict, "push_back");
   if (push_back == NULL) {
     PyErr_BadArgument();
@@ -105,7 +105,7 @@ __init__(PyObject *self, PyObject *source) {
   }
 
   // We need to initialize the this pointer before we can call push_back.
-  ((Dtool_PyInstDef *)self)->_ptr_to_object = (void *)this->_this;
+  DtoolInstance_INIT_PTR(self, this->_this);
 
   Py_ssize_t size = PySequence_Size(source);
   this->_this->reserve(size);

+ 2 - 2
panda/src/gobj/texture.h

@@ -43,10 +43,10 @@
 #include "colorSpace.h"
 #include "geomEnums.h"
 #include "bamCacheRecord.h"
+#include "pnmImage.h"
+#include "pfmFile.h"
 #include "asyncFuture.h"
 
-class PNMImage;
-class PfmFile;
 class TextureContext;
 class FactoryParams;
 class PreparedGraphicsObjects;

+ 10 - 16
panda/src/gobj/texture_ext.cxx

@@ -33,15 +33,12 @@ set_ram_image(PyObject *image, Texture::CompressionMode compression,
   nassertv(compression != Texture::CM_default);
 
   // Check if perhaps a PointerToArray object was passed in.
-  if (DtoolCanThisBeAPandaInstance(image)) {
-    Dtool_PyInstDef *inst = (Dtool_PyInstDef *)image;
-
-    if (inst->_My_Type == &Dtool_ConstPointerToArray_unsigned_char) {
-      _this->set_ram_image(*(const CPTA_uchar *)inst->_ptr_to_object, compression, page_size);
+  if (DtoolInstance_Check(image)) {
+    if (DtoolInstance_TYPE(image) == &Dtool_ConstPointerToArray_unsigned_char) {
+      _this->set_ram_image(*(const CPTA_uchar *)DtoolInstance_VOID_PTR(image), compression, page_size);
       return;
-
-    } else if (inst->_My_Type == &Dtool_PointerToArray_unsigned_char) {
-      _this->set_ram_image(*(const PTA_uchar *)inst->_ptr_to_object, compression, page_size);
+    } else if (DtoolInstance_TYPE(image) == &Dtool_PointerToArray_unsigned_char) {
+      _this->set_ram_image(*(const PTA_uchar *)DtoolInstance_VOID_PTR(image), compression, page_size);
       return;
     }
   }
@@ -99,15 +96,12 @@ set_ram_image(PyObject *image, Texture::CompressionMode compression,
 void Extension<Texture>::
 set_ram_image_as(PyObject *image, const string &provided_format) {
   // Check if perhaps a PointerToArray object was passed in.
-  if (DtoolCanThisBeAPandaInstance(image)) {
-    Dtool_PyInstDef *inst = (Dtool_PyInstDef *)image;
-
-    if (inst->_My_Type == &Dtool_ConstPointerToArray_unsigned_char) {
-      _this->set_ram_image_as(*(const CPTA_uchar *)inst->_ptr_to_object, provided_format);
+  if (DtoolInstance_Check(image)) {
+    if (DtoolInstance_TYPE(image) == &Dtool_ConstPointerToArray_unsigned_char) {
+      _this->set_ram_image_as(*(const CPTA_uchar *)DtoolInstance_VOID_PTR(image), provided_format);
       return;
-
-    } else if (inst->_My_Type == &Dtool_PointerToArray_unsigned_char) {
-      _this->set_ram_image_as(*(const PTA_uchar *)inst->_ptr_to_object, provided_format);
+    } else if (DtoolInstance_TYPE(image) == &Dtool_PointerToArray_unsigned_char) {
+      _this->set_ram_image_as(*(const PTA_uchar *)DtoolInstance_VOID_PTR(image), provided_format);
       return;
     }
   }

+ 1 - 2
panda/src/pgraph/nodePathCollection_ext.cxx

@@ -46,8 +46,7 @@ __init__(PyObject *self, PyObject *sequence) {
     }
 
     NodePath *path;
-    DTOOL_Call_ExtractThisPointerForType(item, &Dtool_NodePath, (void **)&path);
-    if (path == (NodePath *)NULL) {
+    if (!DtoolInstance_GetPointer(item, path, Dtool_NodePath)) {
       // Unable to add item--probably it wasn't of the appropriate type.
       ostringstream stream;
       stream << "Element " << i << " in sequence passed to NodePathCollection constructor is not a NodePath";

+ 2 - 2
panda/src/pgraph/nodePath_ext.cxx

@@ -114,7 +114,7 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
       // It's OK if there's no bamWriter.
       PyErr_Clear();
     } else {
-      DTOOL_Call_ExtractThisPointerForType(py_writer, &Dtool_BamWriter, (void **)&writer);
+      DtoolInstance_GetPointer(py_writer, writer, Dtool_BamWriter);
       Py_DECREF(py_writer);
     }
   }
@@ -228,7 +228,7 @@ py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, vector_uchar dat
       // It's OK if there's no bamReader.
       PyErr_Clear();
     } else {
-      DTOOL_Call_ExtractThisPointerForType(py_reader, &Dtool_BamReader, (void **)&reader);
+      DtoolInstance_GetPointer(py_reader, reader, Dtool_BamReader);
       Py_DECREF(py_reader);
     }
   }

+ 35 - 36
panda/src/pgraph/shaderInput_ext.cxx

@@ -91,80 +91,79 @@ __init__(CPT_InternalName name, PyObject *value, int priority) {
       _this->_stored_vector = LCAST(PN_stdfloat, vec);
     }
 
-  } else if (DtoolCanThisBeAPandaInstance(value)) {
-    Dtool_PyInstDef *inst = (Dtool_PyInstDef *)value;
+  } else if (DtoolInstance_Check(value)) {
     void *ptr;
 
-    if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_Texture))) {
+    if ((ptr = DtoolInstance_UPCAST(value, Dtool_Texture))) {
       _this->_type = ShaderInput::M_texture;
       _this->_value = (Texture *)ptr;
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_NodePath))) {
       _this->_type = ShaderInput::M_nodepath;
       _this->_value = new ParamNodePath(*(const NodePath *)ptr);
 
-    } else if (inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToVoid)) {
-      if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) {
+    } else if (DtoolInstance_UPCAST(value, Dtool_PointerToVoid)) {
+      if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_float))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_float *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_double))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_double *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_int))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_int *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_UnalignedLVecBase4f))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase4f *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LVecBase3f))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase3f *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LVecBase2f))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase2f *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_UnalignedLMatrix4f))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LMatrix4f *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LMatrix3f))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LMatrix3f *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_UnalignedLVecBase4d))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase4d *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LVecBase3d))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase3d *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LVecBase2d))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase2d *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_UnalignedLMatrix4d))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LMatrix4d *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LMatrix3d))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LMatrix3d *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_UnalignedLVecBase4i))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase4i *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LVecBase3i))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase3i *)ptr;
 
-      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) {
+      } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_PointerToArray_LVecBase2i))) {
         _this->_type = ShaderInput::M_numeric;
         _this->_stored_ptr = *(const PTA_LVecBase2i *)ptr;
 
@@ -173,81 +172,81 @@ __init__(CPT_InternalName name, PyObject *value, int priority) {
         return;
       }
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix4f))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LMatrix4f))) {
       _this->_type = ShaderInput::M_numeric;
       _this->_stored_ptr = *(const LMatrix4f *)ptr;
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix3f))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LMatrix3f))) {
       _this->_type = ShaderInput::M_numeric;
       _this->_stored_ptr = *(const LMatrix3f *)ptr;
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix4d))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LMatrix4d))) {
       _this->_type = ShaderInput::M_numeric;
       _this->_stored_ptr = *(const LMatrix4d *)ptr;
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix3d))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LMatrix3d))) {
       _this->_type = ShaderInput::M_numeric;
       _this->_stored_ptr = *(const LMatrix3d *)ptr;
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase4f))) {
       const LVecBase4f &vec = *(const LVecBase4f *)ptr;
       _this->_type = ShaderInput::M_vector;
       _this->_stored_ptr = vec;
       _this->_stored_vector = LCAST(PN_stdfloat, vec);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase3f))) {
       const LVecBase3f &vec = *(const LVecBase3f *)ptr;
       _this->_type = ShaderInput::M_vector;
       _this->_stored_ptr = vec;
       _this->_stored_vector.set(vec[0], vec[1], vec[2], 0);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase2f))) {
       const LVecBase2f &vec = *(const LVecBase2f *)ptr;
       _this->_type = ShaderInput::M_vector;
       _this->_stored_ptr = vec;
       _this->_stored_vector.set(vec[0], vec[1], 0, 0);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase4d))) {
       const LVecBase4d &vec = *(const LVecBase4d *)ptr;
       _this->_type = ShaderInput::M_vector;
       _this->_stored_ptr = vec;
       _this->_stored_vector = LCAST(PN_stdfloat, vec);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase3d))) {
       const LVecBase3d &vec = *(const LVecBase3d *)ptr;
       _this->_type = ShaderInput::M_vector;
       _this->_stored_ptr = vec;
       _this->_stored_vector.set(vec[0], vec[1], vec[2], 0);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase2d))) {
       const LVecBase2d &vec = *(const LVecBase2d *)ptr;
       _this->_type = ShaderInput::M_vector;
       _this->_stored_ptr = vec;
       _this->_stored_vector.set(vec[0], vec[1], 0, 0);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase4i))) {
       const LVecBase4i &vec = *(const LVecBase4i *)ptr;
       _this->_type = ShaderInput::M_numeric;
       _this->_stored_ptr = vec;
       _this->_stored_vector = LCAST(PN_stdfloat, vec);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase3i))) {
       const LVecBase3i &vec = *(const LVecBase3i *)ptr;
       _this->_type = ShaderInput::M_numeric;
       _this->_stored_ptr = vec;
       _this->_stored_vector.set(vec[0], vec[1], vec[2], 0);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_LVecBase2i))) {
       const LVecBase2i &vec = *(const LVecBase2i *)ptr;
       _this->_type = ShaderInput::M_numeric;
       _this->_stored_ptr = vec;
       _this->_stored_vector.set(vec[0], vec[1], 0, 0);
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_ShaderBuffer))) {
       _this->_type = ShaderInput::M_buffer;
       _this->_value = (ShaderBuffer *)ptr;
 
-    } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) {
+    } else if ((ptr = DtoolInstance_UPCAST(value, Dtool_ParamValueBase))) {
       _this->_type = ShaderInput::M_param;
       _this->_value = (ParamValueBase *)ptr;
 

+ 3 - 1
panda/src/putil/typedWritable_ext.cxx

@@ -15,6 +15,8 @@
 
 #ifdef HAVE_PYTHON
 
+#include "bamWriter.h"
+
 #ifndef CPPPARSER
 extern Dtool_PyTypedObject Dtool_BamWriter;
 #endif  // CPPPARSER
@@ -65,7 +67,7 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
       // It's OK if there's no bamWriter.
       PyErr_Clear();
     } else {
-      DTOOL_Call_ExtractThisPointerForType(py_writer, &Dtool_BamWriter, (void **)&writer);
+      DtoolInstance_GetPointer(py_writer, writer, Dtool_BamWriter);
       Py_DECREF(py_writer);
     }
   }