
# HG changeset patch
# User Phil Thompson <phil@riverbankcomputing.com>
# Date 1433842278 -3600
# Node ID 11a92ebd484086e8eb433e3fe6604908bc392af3
# Parent  7d0d2cede024262962132031395f43336916d72e
Fixed the handling of non-pointer object variables so that they are only
wrapped once and the Python object cached.

diff -r 7d0d2cede024 -r 11a92ebd4840 sipgen/gencode.c
--- a/sipgen/gencode.c	Mon Jun 08 17:47:38 2015 +0100
+++ b/sipgen/gencode.c	Tue Jun 09 10:31:18 2015 +0100
@@ -707,6 +707,7 @@
 "#define sipVisitSlot                sipAPI_%s->api_visit_slot\n"
 "#define sipWrappedTypeName(wt)      ((wt)->type->td_cname)\n"
 "#define sipDeprecated               sipAPI_%s->api_deprecated\n"
+"#define sipGetReference             sipAPI_%s->api_get_reference\n"
 "#define sipKeepReference            sipAPI_%s->api_keep_reference\n"
 "#define sipRegisterProxyResolver    sipAPI_%s->api_register_proxy_resolver\n"
 "#define sipRegisterPyType           sipAPI_%s->api_register_py_type\n"
@@ -843,6 +844,7 @@
         ,mname
         ,mname
         ,mname
+        ,mname
         ,mname);
 
     /* The name strings. */
@@ -4470,7 +4472,7 @@
 {
     argType atype = vd->type.atype;
     const char *first_arg, *second_arg, *last_arg;
-    int needsNew, keepRef;
+    int needsNew, key;
 
     if (generating_c || !isStaticVar(vd))
         first_arg = "sipSelf";
@@ -4480,9 +4482,9 @@
     last_arg = (generating_c || usedInCode(vd->getcode, "sipPyType")) ? "sipPyType" : "";
 
     needsNew = ((atype == class_type || atype == mapped_type) && vd->type.nrderefs == 0 && isConstArg(&vd->type));
-    keepRef = (atype == class_type && vd->type.nrderefs == 0 && !isConstArg(&vd->type));
-
-    second_arg = (generating_c || keepRef) ? "sipPySelf" : "";
+    key = ((atype == class_type || atype == mapped_type) && vd->type.nrderefs == 0) ? vd->module->next_key-- : 0;
+
+    second_arg = (generating_c || key < 0) ? "sipPySelf" : "";
 
     prcode(fp,
 "\n"
@@ -4499,7 +4501,7 @@
 "{\n"
         , vd->fqcname, first_arg, second_arg, last_arg);
 
-    if (vd->getcode != NULL || keepRef)
+    if (vd->getcode != NULL || key < 0)
     {
         prcode(fp,
 "    PyObject *sipPy;\n"
@@ -4583,8 +4585,16 @@
             else
                 iff = vd->type.u.cd->iff;
 
-            prcode(fp,
-"    %s sipConvertFrom%sType(", (keepRef ? "sipPy =" : "return"), (needsNew ? "New" : ""));
+            if (key < 0)
+                prcode(fp,
+"    sipPy = sipGetReference(sipPySelf, %d);\n"
+"    if (sipPy)\n"
+"        return sipPy;\n"
+"\n"
+                    , key);
+
+            prcode(fp,
+"    %s sipConvertFrom%sType(", (key < 0 ? "sipPy =" : "return"), (needsNew ? "New" : ""));
 
             if (isConstArg(&vd->type))
                 prcode(fp, "const_cast<%b *>(sipVal)", &vd->type);
@@ -4594,13 +4604,13 @@
             prcode(fp, ", sipType_%C, NULL);\n"
                 , iff->fqcname);
 
-            if (keepRef)
-            {
-                prcode(fp,
-"    sipKeepReference(sipPy, -1, sipPySelf);\n"
+            if (key < 0)
+            {
+                prcode(fp,
+"    sipKeepReference(sipPySelf, %d, sipPy);\n"
 "\n"
 "    return sipPy;\n"
-                    );
+                    , key);
             }
         }
 
diff -r 7d0d2cede024 -r 11a92ebd4840 sipgen/metasrc/parser.y
--- a/sipgen/metasrc/parser.y	Mon Jun 08 17:47:38 2015 +0100
+++ b/sipgen/metasrc/parser.y	Tue Jun 09 10:31:18 2015 +0100
@@ -4518,9 +4518,7 @@
     newmod->encoding = no_type;
     newmod->qobjclass = -1;
     newmod->nrvirthandlers = -1;
-
-    /* -1 is reserved for variable getters. */
-    newmod->next_key = -2;
+    newmod->next_key = -1;
 
     /*
      * The consolidated module support needs these to be in order that they
diff -r 7d0d2cede024 -r 11a92ebd4840 siplib/sip.h.in.in
--- a/siplib/sip.h.in	Mon Jun 08 17:47:38 2015 +0100
+++ b/siplib/sip.h.in	Tue Jun 09 10:31:18 2015 +0100
@@ -68,6 +68,8 @@
  *
  * History:
  *
+ * 11.2 Added sip_api_get_reference() to the private API.
+ *
  * 10.1 Added ctd_final to sipClassTypeDef.
  *      Added ctd_init_mixin to sipClassTypeDef.
  *      Added sip_api_get_mixin_address() to the public API.
@@ -1509,6 +1511,10 @@
             SIP_SSIZE_T len, int flags);
     int (*api_register_proxy_resolver)(const sipTypeDef *td,
             sipProxyResolverFunc resolver);
+    /*
+     * The following are not part of the public API.
+     */
+    PyObject *(*api_get_reference)(PyObject *self, int key);
 } sipAPIDef;
 
 
diff -r 7d0d2cede024 -r 11a92ebd4840 siplib/siplib.c.in
--- a/siplib/siplib.c.in	Mon Jun 08 17:47:38 2015 +0100
+++ b/siplib/siplib.c.in	Tue Jun 09 10:31:18 2015 +0100
@@ -255,6 +255,7 @@
 static void sip_api_clear_any_slot_reference(sipSlot *slot);
 static int sip_api_visit_slot(sipSlot *slot, visitproc visit, void *arg);
 static void sip_api_keep_reference(PyObject *self, int key, PyObject *obj);
+static PyObject *sip_api_get_reference(PyObject *self, int key);
 static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp);
 static void sip_api_set_destroy_on_exit(int value);
 static int sip_api_enable_autoconversion(const sipTypeDef *td, int enable);
@@ -389,6 +390,10 @@
     sip_api_convert_to_typed_array,
     sip_api_convert_to_array,
     sip_api_register_proxy_resolver,
+    /*
+     * The following are not part of the public API.
+     */
+    sip_api_get_reference,
 };
 
 
@@ -8397,6 +8402,33 @@
 
 
 /*
+ * Get an object that has an extra reference.
+ */
+static PyObject *sip_api_get_reference(PyObject *self, int key)
+{
+    PyObject *dict, *key_obj, *obj;
+
+    /* Get the extra references dictionary if there is one. */
+    if ((dict = ((sipSimpleWrapper *)self)->extra_refs) == NULL)
+        return NULL;
+
+#if PY_MAJOR_VERSION >= 3
+    key_obj = PyLong_FromLong(key);
+#else
+    key_obj = PyInt_FromLong(key);
+#endif
+
+    if (key_obj == NULL)
+        return NULL;
+
+    obj = PyDict_GetItem(dict, key_obj);
+    Py_XINCREF(obj);
+
+    return obj;
+}
+
+
+/*
  * Check to see if a Python object can be converted to a type.
  */
 static int sip_api_can_convert_to_type(PyObject *pyObj, const sipTypeDef *td,

