# HG changeset patch # User Abhinav Tripathi # Date 1492074648 25200 # Node ID fc0fb94161de56ce7925bdbff589ebd03ef40a08 # Parent a1fb6575f6ddcf6124e26c1c2678918e2524ab86 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 diff -r a1fb6575f6dd -r fc0fb94161de Makefile.am --- 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)) diff -r a1fb6575f6dd -r fc0fb94161de oct-py-object.h --- /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 +. + +*/ + +#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 + diff -r a1fb6575f6dd -r fc0fb94161de oct-py-util.cc --- 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 @@ -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 (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; }