add support for cyclic garbage collection to eTimer and eSocketNotifier
[vuplus_dvbapp] / lib / python / python.cpp
index 2d84287..ad029fb 100644 (file)
-#include <lib/python/python.h>
 #include <lib/base/eerror.h>
                 /* avoid warnigs :) */
 #undef _POSIX_C_SOURCE
 #define _POSIX_C_SOURCE 200112L
-#include <Python.h>
-
 extern "C" void init_enigma();
+extern "C" void eBaseInit(void);
+extern void bsodFatal();
 
-DEFINE_REF(TestObj);
-
-TestObj::TestObj()
-{
-       eDebug("create %p", this);
-}
-
-TestObj::~TestObj()
-{
-       eDebug("destroy %p", this);
-}
+#define SKIP_PART2
+#include <lib/python/python.h>
+#undef SKIP_PART2
 
-#if 0
-ePyObject::ePyObject(void *ptr): m_object(ptr)
+#ifdef PYTHON_REFCOUNT_DEBUG
+ePyObject &ePyObject::operator=(PyObject *ob)
 {
-       Py_XINCREF((PyObject*)ptr);
+       m_ob=ob;
+       m_file=0;
+       m_line=0;
+       m_from=m_to=0;
+       m_erased=false;
+       return *this;
 }
 
-ePyObject::ePyObject(ePyObject &p)
+ePyObject &ePyObject::operator=(const ePyObject &ob)
 {
-       m_object = p.m_object;
-       Py_XINCREF((PyObject*)m_object);
+       m_ob=ob.m_ob;
+       m_file=ob.m_file;
+       m_line=ob.m_line;
+       m_from=ob.m_from;
+       m_to=ob.m_to;
+       m_erased=ob.m_erased;
+       return *this;
 }
 
-ePyObject::ePyObject(): m_object(0)
+ePyObject::operator PyObject*()
 {
+       if (m_ob)
+       {
+               if (!m_erased && m_ob->ob_refcnt > 0)
+                       return m_ob;
+               eDebug("invalid access PyObject %s with refcount <= 0 %d",
+                       m_erased ? "deleted" : "undeleted", m_ob->ob_refcnt);
+               if (m_file)
+                       eDebug("last modified in file %s line %d from %d to %d",
+                               m_file, m_line, m_from, m_to);
+               bsodFatal();
+       }
+       return 0;
 }
 
-ePyObject::~ePyObject()
+void ePyObject::incref(const char *file, int line)
 {
-       Py_XDECREF((PyObject*)m_object);
+       if (!m_ob)
+       {
+               eDebug("invalid incref python object with null pointer %s %d!!!", file, line);
+               if (m_file)
+                       eDebug("last modified in file %s line %d from %d to %d",
+                               m_file, m_line, m_from, m_to);
+               bsodFatal();
+       }
+       if (m_erased || m_ob->ob_refcnt <= 0)
+       {
+               eDebug("invalid incref %s python object with refcounting value %d in file %s line %d!!!",
+                       m_erased ? "deleted" : "undeleted", m_ob->ob_refcnt, file, line);
+               if (m_file)
+                       eDebug("last modified in file %s line %d from %d to %d",
+                               m_file, m_line, m_from, m_to);
+               bsodFatal();
+       }
+       if (m_ob->ob_refcnt == 0x7FFFFFFF)
+       {
+               eDebug("invalid incref %s python object with refcounting value %d (MAX_INT!!!) in file %s line %d!!!",
+                       m_erased ? "deleted" : "undeleted", m_ob->ob_refcnt, file, line);
+               if (m_file)
+                       eDebug("last modified in file %s line %d from %d to %d",
+                               m_file, m_line, m_from, m_to);
+               bsodFatal();
+       }
+       m_file = file;
+       m_line = line;
+       m_from = m_ob->ob_refcnt;
+       m_to = m_from+1;
+       Py_INCREF(m_ob);
 }
 
-ePyObject &ePyObject::operator=(ePyObject &p)
+void ePyObject::decref(const char *file, int line)
 {
-       Py_XDECREF((PyObject*)m_object);
-       m_object = p.m_object;
-       Py_XINCREF((PyObject*)m_object);
-       return *this;
+       if (!m_ob)
+       {
+               eDebug("invalid decref python object with null pointer %s %d!!!", file, line);
+               if (m_file)
+                       eDebug("last modified in file %s line %d from %d to %d",
+                               m_file, m_line, m_from, m_to);
+               bsodFatal();
+       }
+       if (m_erased || m_ob->ob_refcnt <= 0)
+       {
+               eDebug("invalid decref %s python object with refcounting value %d in file %s line %d!!!",
+                       m_erased ? "deleted" : "undeleted", m_ob->ob_refcnt, file, line);
+               if (m_file)
+                       eDebug("last modified in file %s line %d from %d to %d",
+                               m_file, m_line, m_from, m_to);
+               bsodFatal();
+       }
+       m_file = file;
+       m_line = line;
+       m_from = m_ob->ob_refcnt;
+       m_to = m_from-1;
+       m_erased = !m_to;
+       Py_DECREF(m_ob);
 }
+#endif  // PYTHON_REFCOUNT_DEBUG
 
-ePyObject &ePyObject::operator=(void *object)
-{
-       Py_XDECREF((PyObject*)m_object);
-       m_object = object;
-       Py_XINCREF((PyObject*)m_object);
-       return *this;
-}
-#endif
+#define SKIP_PART1
+#include <lib/python/python.h>
+#undef SKIP_PART1
 
 ePython::ePython()
 {
-       Py_Initialize();
+//     Py_VerboseFlag = 1;
+       
+//     Py_OptimizeFlag = 1;
        
+       Py_Initialize();
+       PyEval_InitThreads();
+
        init_enigma();
+       eBaseInit();
 }
 
 ePython::~ePython()
@@ -71,14 +135,13 @@ ePython::~ePython()
 
 int ePython::execute(const std::string &pythonfile, const std::string &funcname)
 {
-       PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pValue;
-       
+       ePyObject pName, pModule, pDict, pFunc, pArgs, pValue;
        pName = PyString_FromString(pythonfile.c_str());
-       
+
        pModule = PyImport_Import(pName);
        Py_DECREF(pName);
        
-       if (pModule != NULL)
+       if (pModule)
        {
                pDict = PyModule_GetDict(pModule);
                
@@ -90,7 +153,7 @@ int ePython::execute(const std::string &pythonfile, const std::string &funcname)
                                // implement arguments..
                        pValue = PyObject_CallObject(pFunc, pArgs);
                        Py_DECREF(pArgs);
-                       if (pValue != NULL)
+                       if (pValue)
                        {
                                printf("Result of call: %ld\n", PyInt_AsLong(pValue));
                                Py_DECREF(pValue);
@@ -110,14 +173,14 @@ int ePython::execute(const std::string &pythonfile, const std::string &funcname)
        return 0;
 }
 
-int ePython::call(PyObject *pFunc, PyObject *pArgs)
+int ePython::call(ePyObject pFunc, ePyObject pArgs)
 {
        int res = -1;
-       PyObject *pValue;
+       ePyObject pValue;
        if (pFunc && PyCallable_Check(pFunc))
        {
                pValue = PyObject_CallObject(pFunc, pArgs);
-               if (pValue != NULL)
+               if (pValue)
                {
                        if (PyInt_Check(pValue))
                                res = PyInt_AsLong(pValue);
@@ -127,31 +190,33 @@ int ePython::call(PyObject *pFunc, PyObject *pArgs)
                } else
                {
                        PyErr_Print();
+                       ePyObject FuncStr = PyObject_Str(pFunc);
+                       ePyObject ArgStr = PyObject_Str(pArgs);
+                       eDebug("(PyObject_CallObject(%s,%s) failed)", PyString_AS_STRING(FuncStr), PyString_AS_STRING(ArgStr));
+                       Py_DECREF(FuncStr);
+                       Py_DECREF(ArgStr);
+                       bsodFatal();
                }
        }
        return res;
 }
 
-PyObject *ePython::resolve(const std::string &pythonfile, const std::string &funcname)
+ePyObject ePython::resolve(const std::string &pythonfile, const std::string &funcname)
 {
-       PyObject *pName, *pModule, *pDict, *pFunc;
+       ePyObject pName, pModule, pDict, pFunc;
 
        pName = PyString_FromString(pythonfile.c_str());
 
        pModule = PyImport_Import(pName);
        Py_DECREF(pName);
        
-       if (pModule != NULL)
+       if (pModule)
        {
                pDict = PyModule_GetDict(pModule);
                pFunc = PyDict_GetItemString(pDict, funcname.c_str());
                Py_XINCREF(pFunc);
                Py_DECREF(pModule);
-               return pFunc;
-       } else
-       {
-               if (PyErr_Occurred())
-                       PyErr_Print();
-               return 0;
-       }
+       } else if (PyErr_Occurred())
+               PyErr_Print();
+       return pFunc;
 }