changeset 397:fc0fb94161de

Add a wrapper for PyObject pointers (fixes issue #81) * oct-py-object.h: Added the new class python_object * oct-py-util.cc: Edited the existing code to use the new wrapper * Makefile.am: Add the new header to the list of headers
author Abhinav Tripathi <genuinelucifer@gmail.com>
date Thu, 13 Apr 2017 02:10:48 -0700
parents a1fb6575f6dd
children 3905052ebe1d
files Makefile.am oct-py-object.h oct-py-util.cc
diffstat 3 files changed, 129 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Fri Apr 07 11:15:05 2017 -0700
+++ b/Makefile.am	Thu Apr 13 02:10:48 2017 -0700
@@ -71,7 +71,8 @@
   oct-py-types.h \
   oct-py-util.h \
   octave_to_python.h \
-  python_to_octave.h
+  python_to_octave.h \
+  oct-py-object.h
 
 TST_FILES = $(addsuffix -tst,$(OCT_SOURCE_FILES))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/oct-py-object.h	Thu Apr 13 02:10:48 2017 -0700
@@ -0,0 +1,105 @@
+/*
+
+Copyright (C) 2017 Abhinav Tripathi
+
+This file is part of Pytave.
+
+Pytave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Pytave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Pytave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (pytave_oct_py_object_h)
+#define pytave_oct_py_object_h
+
+namespace pytave
+{
+
+  class python_object
+  {
+  public:
+    python_object (PyObject *obj = 0)
+    {
+      pyobj = obj;
+      isowned = pyobj != 0;
+    }
+
+    python_object (const python_object& oth)
+    {
+      pyobj = oth.pyobj;
+      isowned = oth.isowned;
+      if (isowned)
+        Py_INCREF (pyobj);
+    }
+
+    ~python_object ()
+    {
+      if (isowned)
+        Py_DECREF (pyobj);
+    }
+
+    python_object& operator= (const python_object& oth)
+    {
+      if (isowned)
+        Py_DECREF (pyobj);
+      pyobj = oth.pyobj;
+      isowned = oth.isowned;
+      if (isowned)
+        Py_INCREF (pyobj);
+      return *this;
+    }
+
+    python_object& operator= (PyObject *obj)
+    {
+      if (isowned)
+        Py_DECREF (pyobj);
+      pyobj = obj;
+      isowned = pyobj != 0;
+      if (isowned)
+        Py_INCREF (pyobj);
+      return *this;
+    }
+
+    operator bool () const
+    {
+      return isowned;
+    }
+
+    operator PyObject *()
+    {
+      return pyobj;
+    }
+
+    bool is_none ()
+    {
+      return pyobj && pyobj == Py_None;
+    }
+
+    PyObject *release ()
+    {
+      isowned = false;
+      PyObject *ret = pyobj;
+      pyobj = 0;
+      return ret;
+    }
+
+  private:
+    PyObject *pyobj;
+    bool isowned;
+  };
+
+}
+
+#endif
+
--- a/oct-py-util.cc	Fri Apr 07 11:15:05 2017 -0700
+++ b/oct-py-util.cc	Thu Apr 13 02:10:48 2017 -0700
@@ -29,6 +29,7 @@
 
 #include "oct-py-types.h"
 #include "oct-py-util.h"
+#include "oct-py-object.h"
 
 // FIXME: only here for boost::python::error_already_set
 #include <boost/python.hpp>
@@ -72,9 +73,8 @@
 PyObject *
 py_find_function (const std::string& module, const std::string& name)
 {
-  PyObject *mod = py_import_module (module);
+  python_object mod = py_import_module (module);
   PyObject *func =  py_find_function (mod, name);
-  Py_XDECREF (mod);
   return func;
 }
 
@@ -100,11 +100,10 @@
 PyObject *
 py_find_type (const std::string& name)
 {
-  PyObject *obj = py_find_function (name);
+  python_object obj = py_find_function (name);
   if (obj && PyType_Check (obj))
-    return obj;
+    return obj.release ();
 
-  Py_XDECREF (obj);
   return 0;
 }
 
@@ -128,24 +127,20 @@
 {
   std::string retval;
 
-  PyObject *type = obj ? PyObject_GetAttrString (obj, "__class__") : 0;
+  python_object type = obj ? PyObject_GetAttrString (obj, "__class__") : 0;
   if (type)
     {
-      PyObject *mod = PyObject_GetAttrString (type, "__module__");
+      python_object mod = PyObject_GetAttrString (type, "__module__");
 
-      PyObject *name = 0;
+      python_object name;
       if (PyObject_HasAttrString (type, "__qualname__"))
         name = PyObject_GetAttrString (type, "__qualname__");
       else
         name = PyObject_GetAttrString (type, "__name__");
 
-      std::string mod_str = (mod && mod != Py_None) ? extract_py_str (mod) : "";
+      std::string mod_str = !mod.is_none () ? extract_py_str (mod) : "";
       std::string name_str = name ? extract_py_str (name) : "";
 
-      Py_DECREF (type);
-      Py_XDECREF (mod);
-      Py_XDECREF (name);
-
       if (mod_str.empty () || mod_str == py_builtins_module_name ())
         retval = name_str;
       else
@@ -163,8 +158,8 @@
 {
   if (! objstore)
     {
-      PyObject *main = py_import_module ("__main__");
-      PyObject *ns = main ? PyObject_GetAttrString (main, "__dict__") : 0;
+      python_object main = py_import_module ("__main__");
+      python_object ns = main ? PyObject_GetAttrString (main, "__dict__") : 0;
       PyObject *dict = ns ? PyDict_GetItemString (ns, "_in_octave") : 0;
 
       if (dict)
@@ -188,23 +183,21 @@
 void
 py_objstore_del (uint64_t key)
 {
-  PyObject *store = py_objstore ();
-  PyObject *key_obj = make_py_int (key);
-  PyObject *key_fmt = PyNumber_ToBase (key_obj, 16);
+  python_object store = py_objstore ();
+  python_object key_obj = make_py_int (key);
+  python_object key_fmt = PyNumber_ToBase (key_obj, 16);
   PyDict_DelItem (store, key_fmt);
-  Py_DECREF (key_fmt);
-  Py_DECREF (key_obj);
+  store.release ();
 }
 
 PyObject *
 py_objstore_get (uint64_t key)
 {
-  PyObject *store = py_objstore ();
-  PyObject *key_obj = make_py_int (key);
-  PyObject *key_fmt = PyNumber_ToBase (key_obj, 16);
+  python_object store = py_objstore ();
+  python_object key_obj = make_py_int (key);
+  python_object key_fmt = PyNumber_ToBase (key_obj, 16);
   PyObject *obj = PyDict_GetItem (store, key_fmt);
-  Py_DECREF (key_fmt);
-  Py_DECREF (key_obj);
+  store.release ();
   if (obj)
     Py_INCREF (obj);
   return obj;
@@ -213,13 +206,12 @@
 uint64_t
 py_objstore_put (PyObject *obj)
 {
-  PyObject *store = py_objstore ();
+  python_object store = py_objstore ();
   uint64_t key = reinterpret_cast<uint64_t> (obj);
-  PyObject *key_obj = make_py_int (key);
-  PyObject *key_fmt = PyNumber_ToBase (key_obj, 16);
+  python_object key_obj = make_py_int (key);
+  python_object key_fmt = PyNumber_ToBase (key_obj, 16);
   PyDict_SetItem (store, key_fmt, obj);
-  Py_DECREF (key_fmt);
-  Py_DECREF (key_obj);
+  store.release ();
   return key;
 }