PLearn 0.1
PythonObjectWrapper.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PythonObjectWrapper.cc
00004 //
00005 // Copyright (C) 2005-2006 Nicolas Chapados
00006 // Copyright (C) 2007 Xavier Saint-Mleux, ApSTAT Technologies inc.
00007 //
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 //
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 //
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 //
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 //
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 //
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00036 /* *******************************************************
00037    * $Id: .pyskeleton_header 544 2003-09-01 00:05:31Z plearner $
00038    ******************************************************* */
00039 
00040 // Authors: Nicolas Chapados
00041 
00044 #define PL_LOG_MODULE_NAME "PythonObjectWrapper"
00045 
00046 // Must include Python first...
00047 #include "PythonObjectWrapper.h"
00048 #include "PythonEmbedder.h"
00049 #include "PythonExtension.h"
00050 
00051 // From C/C++ stdlib
00052 #include <stdio.h>
00053 #include <algorithm>
00054 
00055 // From PLearn
00056 #include <plearn/base/plerror.h>
00057 #include <plearn/vmat/VMat.h>
00058 #include <plearn/base/RemoteTrampoline.h>
00059 #include <plearn/base/HelpSystem.h>
00060 #include <plearn/var/VarArray.h>
00061 #include <plearn/base/RealMapping.h> // for RealRange
00062 #include <plearn/vmat/VMField.h>
00063 #include <plearn/io/pl_log.h>
00064 
00065 namespace PLearn {
00066 using namespace std;
00067 
00068 // Error-reporting
00069 void PLPythonConversionError(const char* function_name,
00070                              PyObject* pyobj, bool print_traceback)
00071 {
00072     if (print_traceback) {
00073         fprintf(stderr,"For python object: ");
00074         PyObject_Print(pyobj, stderr, Py_PRINT_RAW);
00075     }
00076     if (PyErr_Occurred()) PyErr_Print();
00077     PLERROR("Cannot convert Python object using %s", function_name);
00078 }
00079 
00080 // Python initialization
00081 void PythonObjectWrapper::initializePython()
00082 {
00083     static bool numarray_initialized = false;
00084     if (! numarray_initialized) {
00085         // must be in each translation unit that makes use of libnumarray;
00086         // weird stuff related to table of function pointers that's being
00087         // initialized into a STATIC VARIABLE of the translation unit!
00088         import_array();//needed for PyArray_DescFromType (will segfault otherwise)
00089         import_libnumarray();
00090         numarray_initialized = true;
00091     }
00092 }
00093 
00094 
00095 //#####  ConvertFromPyObject  #################################################
00096 
00097 PyObject* ConvertFromPyObject<PyObject*>::convert(PyObject* pyobj, bool print_traceback)
00098 {
00099     PLASSERT( pyobj );
00100     return pyobj;
00101 }
00102 
00103 bool ConvertFromPyObject<bool>::convert(PyObject* pyobj, bool print_traceback)
00104 {
00105     PLASSERT( pyobj );
00106     return PyObject_IsTrue(pyobj) != 0;
00107 }
00108 
00109 
00110 double ConvertFromPyObject<double>::convert(PyObject* pyobj,
00111                                             bool print_traceback)
00112 {
00113     PLASSERT( pyobj );
00114     if(PyFloat_Check(pyobj))
00115         return PyFloat_AS_DOUBLE(pyobj);
00116     if(PyLong_Check(pyobj))
00117         return PyLong_AsDouble(pyobj);
00118     if(PyInt_Check(pyobj))
00119         return (double)PyInt_AS_LONG(pyobj);
00120     if(PyArray_CheckScalar(pyobj))
00121     {
00122         double ret= 0.;
00123         PyArray_CastScalarToCtype(pyobj, &ret, PyArray_DescrFromType(NPY_DOUBLE));
00124         return ret;
00125     }
00126     PLPythonConversionError("ConvertFromPyObject<double>", pyobj,
00127                             print_traceback);
00128     return 0;//shut up compiler
00129 }
00130 
00131 float ConvertFromPyObject<float>::convert(PyObject* pyobj,
00132                                           bool print_traceback)
00133 {
00134     PLASSERT( pyobj );
00135     if(PyFloat_Check(pyobj))
00136         return (float)PyFloat_AS_DOUBLE(pyobj);
00137     if(PyLong_Check(pyobj))
00138         return (float)PyLong_AsDouble(pyobj);
00139     if(PyInt_Check(pyobj))
00140         return (float)PyInt_AS_LONG(pyobj);
00141     if(PyArray_CheckScalar(pyobj))
00142     {
00143         float ret= 0.;
00144         PyArray_CastScalarToCtype(pyobj, &ret, PyArray_DescrFromType(NPY_FLOAT));
00145         return ret;
00146     }
00147     PLPythonConversionError("ConvertFromPyObject<float>", pyobj,
00148                             print_traceback);
00149     return 0;//shut up compiler
00150 }
00151 
00152 string ConvertFromPyObject<string>::convert(PyObject* pyobj,
00153                                             bool print_traceback)
00154 {
00155     PLASSERT(pyobj);
00156 
00157     // if unicode, encode into a string (utf8) then return
00158     if(PyUnicode_Check(pyobj))
00159     {
00160         PyObject* pystr= PyUnicode_AsUTF8String(pyobj);
00161         if(!pystr)
00162         {
00163             if(PyErr_Occurred()) PyErr_Print();
00164             Py_DECREF(pystr);
00165             PLERROR("in ConvertFromPyObject<string>::convert : "
00166                     "Unicode to string conversion failed.");
00167         }
00168         string str= PyString_AsString(pystr);
00169         Py_DECREF(pystr);
00170         return str;
00171     }
00172     
00173     // otherwise, should already be a string
00174     if(!PyString_Check(pyobj))
00175         PLPythonConversionError("ConvertFromPyObject<string>", pyobj,
00176                                 print_traceback);
00177     return PyString_AsString(pyobj);
00178 }
00179 
00180 PPath ConvertFromPyObject<PPath>::convert(PyObject* pyobj,
00181                                           bool print_traceback)
00182 {
00183     return PPath(ConvertFromPyObject<string>::convert(pyobj, print_traceback));
00184 }
00185 
00186 PPointable* ConvertFromPyObject<PPointable*>::convert(PyObject* pyobj,
00187                                                       bool print_traceback)
00188 {
00189     PLASSERT(pyobj);
00190     if (! PyCObject_Check(pyobj))
00191         PLPythonConversionError("ConvertFromPyObject<PPointable*>", pyobj,
00192                                 print_traceback);
00193     return static_cast<PPointable*>(PyCObject_AsVoidPtr(pyobj));
00194 }
00195 
00196 Object* ConvertFromPyObject<Object*>::convert(PyObject* pyobj,
00197                                               bool print_traceback)
00198 {
00199 //     DBG_MODULE_LOG << "ConvertFromPyObject<Object*>::convert("
00200 //                    << (void*)pyobj << ' ' << PythonObjectWrapper(pyobj)
00201 //                    << ')' << endl;
00202     PLASSERT(pyobj);
00203     if(pyobj == Py_None)
00204         return 0;
00205 
00206     if(!PyObject_HasAttrString(pyobj, const_cast<char*>("_cptr")))
00207     {
00208         PLERROR("in ConvertFromPyObject<Object*>::convert : "
00209                 "python object has no attribute '_cptr'");
00210         return 0;
00211     }
00212     PyObject* cptr= PyObject_GetAttrString(pyobj, const_cast<char*>("_cptr"));
00213 
00214     if (! PyCObject_Check(cptr))
00215         PLPythonConversionError("ConvertFromPyObject<Object*>", pyobj,
00216                                 print_traceback);
00217     Object* obj= static_cast<Object*>(PyCObject_AsVoidPtr(cptr));
00218 
00219     Py_DECREF(cptr);
00220 //     DBG_MODULE_LOG << "EXITING ConvertFromPyObject<Object*>::convert("
00221 //                    << (void*)pyobj << ' ' << PythonObjectWrapper(pyobj)
00222 //                    << ')' << " => " << (void*)obj << ' ' << obj->asString() << endl;
00223     return obj;
00224 }
00225 
00226 
00227 void ConvertFromPyObject<Vec>::convert(PyObject* pyobj, Vec& v,
00228                                        bool print_traceback)
00229 {
00230     PLASSERT( pyobj );
00231     PyObject* pyarr0= PyArray_CheckFromAny(pyobj, NULL,
00232                                            1, 1, NPY_CARRAY_RO, Py_None);
00233     if(!pyarr0)
00234     {
00235         Py_XDECREF(pyarr0);
00236         PLPythonConversionError("ConvertFromPyObject<Vec>", pyobj,
00237                                 print_traceback);
00238     }
00239     PyObject* pyarr= 
00240         PyArray_CastToType(reinterpret_cast<PyArrayObject*>(pyarr0),
00241                            PyArray_DescrFromType(PL_NPY_REAL), 0);
00242     Py_XDECREF(pyarr0);
00243     if(!pyarr)
00244     {
00245         Py_XDECREF(pyarr);
00246         PLPythonConversionError("ConvertFromPyObject<Vec>", pyobj,
00247                                 print_traceback);
00248     }
00249     v.resize(PyArray_DIM(pyarr,0));
00250     v.copyFrom((real*)(PyArray_DATA(pyarr)), PyArray_DIM(pyarr,0));
00251     Py_XDECREF(pyarr);
00252 }
00253 
00254 Vec ConvertFromPyObject<Vec>::convert(PyObject* pyobj, bool print_traceback)
00255 {
00256     Vec v;
00257     convert(pyobj, v, print_traceback);
00258     return v;
00259 }
00260 
00261 void ConvertFromPyObject<Mat>::convert(PyObject* pyobj, Mat& m,
00262                                        bool print_traceback)
00263 {
00264     PLASSERT( pyobj );
00265     PyObject* pyarr0= PyArray_CheckFromAny(pyobj, NULL,
00266                                            2, 2, NPY_CARRAY_RO, Py_None);
00267     if(!pyarr0)
00268         PLPythonConversionError("ConvertFromPyObject<Mat>", pyobj,
00269                                 print_traceback);
00270     PyObject* pyarr= 
00271         PyArray_CastToType(reinterpret_cast<PyArrayObject*>(pyarr0),
00272                            PyArray_DescrFromType(PL_NPY_REAL), 0);
00273     Py_XDECREF(pyarr0);
00274     if(!pyarr)
00275         PLPythonConversionError("ConvertFromPyObject<Mat>", pyobj,
00276                                 print_traceback);
00277     m.resize(PyArray_DIM(pyarr,0), PyArray_DIM(pyarr,1));
00278     m.toVec().copyFrom((real*)(PyArray_DATA(pyarr)),
00279                        PyArray_DIM(pyarr,0) * PyArray_DIM(pyarr,1));
00280     Py_XDECREF(pyarr);
00281 }
00282 
00283 Mat ConvertFromPyObject<Mat>::convert(PyObject* pyobj, bool print_traceback)
00284 {
00285     Mat m;
00286     convert(pyobj, m, print_traceback);
00287     return m;
00288 }
00289 
00290 //VMat ConvertFromPyObject<VMat>::convert(PyObject* pyobj,
00291 //                                        bool print_traceback)
00292 PP<VMatrix> ConvertFromPyObject<PP<VMatrix> >::convert(PyObject* pyobj,
00293                                                        bool print_traceback)
00294 {
00295     PLASSERT(pyobj);
00296     if(pyobj == Py_None)
00297         return 0;
00298     if(PyObject_HasAttrString(pyobj, const_cast<char*>("_cptr")))
00299         return static_cast<VMatrix*>(
00300             ConvertFromPyObject<Object*>::convert(pyobj, print_traceback));
00301     Mat m;
00302     ConvertFromPyObject<Mat>::convert(pyobj, m, print_traceback);
00303     return VMat(m);
00304 }
00305 
00306 PythonObjectWrapper ConvertFromPyObject<PythonObjectWrapper>::convert(PyObject* pyobj, bool print_traceback)
00307 {
00308     PLASSERT(pyobj);
00309     return PythonObjectWrapper(pyobj);
00310 }
00311 
00312 CopiesMap ConvertFromPyObject<CopiesMap>::convert(PyObject* pyobj,
00313                                                   bool print_traceback)
00314 {
00315     PLASSERT( pyobj );
00316     if (! PyDict_Check(pyobj))
00317         PLPythonConversionError("ConvertFromPyObject<CopiesMap>", 
00318                                 pyobj, print_traceback);
00319 #if PL_PYTHON_VERSION>=250
00320     Py_ssize_t pos = 0;
00321 #else
00322     int pos = 0;
00323 #endif
00324     CopiesMap copies;
00325     PyObject *key, *val;
00326     while(PyDict_Next(pyobj, &pos, &key, &val)) 
00327     {
00328         if(!PyCObject_Check(key))
00329             PLPythonConversionError("ConvertFromPyObject<CopiesMap> "
00330                                     "(key is not a cptr)", 
00331                                     key, print_traceback);
00332         if(!PyCObject_Check(val))
00333             PLPythonConversionError("ConvertFromPyObject<CopiesMap> "
00334                                     "(val is not a cptr)", 
00335                                     val, print_traceback);
00336         copies.insert(make_pair(PyCObject_AsVoidPtr(key),
00337                                 PyCObject_AsVoidPtr(val)));
00338     }
00339     return copies;
00340 }
00341 
00342 VarArray ConvertFromPyObject<VarArray>::convert(PyObject* pyobj,
00343                                                 bool print_traceback)
00344 {
00345     return static_cast<VarArray>(ConvertFromPyObject<TVec<Var> >::convert(pyobj, print_traceback));
00346 }
00347 
00348 RealRange ConvertFromPyObject<RealRange>::convert(PyObject* pyobj, bool print_traceback)
00349 {
00350     PLASSERT(pyobj);
00351     PyObject* py_leftbracket= PyObject_GetAttrString(pyobj, const_cast<char*>("leftbracket"));
00352     if(!py_leftbracket)
00353         PLPythonConversionError("ConvertFromPyObject<RealRange>: "
00354                                 "not a RealRange (no 'leftbracket' attr.)",
00355                                 pyobj, print_traceback);
00356     string leftbracket= ConvertFromPyObject<string>::convert(py_leftbracket, print_traceback);
00357     Py_DECREF(py_leftbracket);
00358     PyObject* py_low= PyObject_GetAttrString(pyobj, const_cast<char*>("low"));
00359     if(!py_low) 
00360         PLPythonConversionError("ConvertFromPyObject<RealRange>: "
00361                                 "not a RealRange (no 'low' attr.)",
00362                                 pyobj, print_traceback);
00363     real low= ConvertFromPyObject<real>::convert(py_low, print_traceback);
00364     Py_DECREF(py_low);
00365     PyObject* py_high= PyObject_GetAttrString(pyobj, const_cast<char*>("high"));
00366     if(!py_high) 
00367         PLPythonConversionError("ConvertFromPyObject<RealRange>: "
00368                                 "not a RealRange (no 'high' attr.)",
00369                                 pyobj, print_traceback);
00370     real high= ConvertFromPyObject<real>::convert(py_high, print_traceback);
00371     Py_DECREF(py_high);
00372     PyObject* py_rightbracket= PyObject_GetAttrString(pyobj, const_cast<char*>("rightbracket"));
00373     if(!py_rightbracket) 
00374         PLPythonConversionError("ConvertFromPyObject<RealRange>: "
00375                                 "not a RealRange (no 'rightbracket' attr.)",
00376                                 pyobj, print_traceback);
00377     string rightbracket= ConvertFromPyObject<string>::convert(py_rightbracket, print_traceback);
00378     Py_DECREF(py_rightbracket);
00379     return RealRange(leftbracket[0], low, high, rightbracket[0]);
00380 }
00381 
00382 VMField ConvertFromPyObject<VMField>::convert(PyObject* pyobj, bool print_traceback)
00383 {
00384     PLASSERT(pyobj);
00385     PyObject* py_name = PyObject_GetAttrString(pyobj, const_cast<char*>("name"));
00386     if (!py_name)
00387         PLPythonConversionError("ConvertFromPyObject<VMField>: not a VMField (no 'name' attr.)",
00388                                 pyobj, print_traceback);
00389     string name = ConvertFromPyObject<string>::convert(py_name, print_traceback);
00390     Py_DECREF(py_name);
00391 
00392     PyObject* py_fieldtype = PyObject_GetAttrString(pyobj, const_cast<char*>("fieldtype"));
00393     if(!py_fieldtype) 
00394         PLPythonConversionError("ConvertFromPyObject<VMField>: not a VMField (no 'fieldtype' attr.)",
00395                                 pyobj, print_traceback);
00396     VMField::FieldType fieldtype = (VMField::FieldType)ConvertFromPyObject<int>::convert(py_fieldtype, print_traceback);
00397     Py_DECREF(py_fieldtype);
00398 
00399     return VMField(name, fieldtype);
00400 }
00401 
00402 template<> int numpyType<bool>()               { return NPY_BOOL; }
00403 template<> int numpyType<signed char>()        { return NPY_BYTE; }
00404 template<> int numpyType<unsigned char>()      { return NPY_UBYTE; }
00405 template<> int numpyType<signed short>()       { return NPY_SHORT; }
00406 template<> int numpyType<unsigned short>()     { return NPY_USHORT; }
00407 template<> int numpyType<signed int>()         { return NPY_INT; }
00408 template<> int numpyType<unsigned int>()       { return NPY_UINT; }
00409 template<> int numpyType<signed long>()        { return NPY_LONG; }
00410 template<> int numpyType<unsigned long>()      { return NPY_ULONG; }
00411 template<> int numpyType<signed long long>()   { return NPY_LONGLONG; }
00412 template<> int numpyType<unsigned long long>() { return NPY_ULONGLONG; }
00413 template<> int numpyType<float>()              { return NPY_FLOAT; }
00414 template<> int numpyType<double>()             { return NPY_DOUBLE; }
00415 template<> int numpyType<long double>()        { return NPY_LONGDOUBLE; }
00416 
00417 PyObject* convertArrayCheck(PyObject* pyobj, int numpy_type, int ndim, bool print_traceback)
00418 {
00419     PythonGlobalInterpreterLock gil;         // For thread-safety
00420     static PythonEmbedder embedder;
00421     PythonObjectWrapper::initializePython();
00422 
00423     if(!PyArray_Check(pyobj)) return 0; //not an array
00424 
00425     PyObject* pyarr0= PyArray_CheckFromAny(pyobj, NULL,
00426                                            ndim, ndim, NPY_CARRAY_RO, Py_None);
00427     PyObject* pyarr= 
00428         PyArray_CastToType(reinterpret_cast<PyArrayObject*>(pyarr0),
00429                            PyArray_DescrFromType(numpy_type), 0);
00430     Py_XDECREF(pyarr0);
00431     if(!pyarr)
00432         PLPythonConversionError("convertArrayCheck", pyobj,
00433                                 print_traceback);
00434     return pyarr;
00435 }
00436 
00437 //#####  Constructors+Destructors  ############################################
00438 
00439 PythonObjectWrapper::PythonObjectWrapper(OwnershipMode o,
00440                                          // unused in this overload
00441                                          bool acquire_gil)
00442     : m_ownership(o),
00443       m_object(Py_None)
00444 {
00445     if (m_ownership == control_ownership)
00446     {Py_XINCREF(m_object);}
00447 }
00448 
00450 PythonObjectWrapper::PythonObjectWrapper(PyObject* pyobj, OwnershipMode o,
00451                                          // unused in this overload
00452                                          bool acquire_gil)
00453     : m_ownership(o),
00454       m_object(pyobj)
00455 {
00456     if (m_ownership == control_ownership)
00457     {Py_XINCREF(m_object);}
00458 }
00459 
00460 
00461 // Copy constructor: increment refcount if controlling ownership.
00462 // No need to manage GIL.
00463 PythonObjectWrapper::PythonObjectWrapper(const PythonObjectWrapper& other)
00464     : m_ownership(other.m_ownership),
00465       m_object(other.m_object)
00466 {
00467     if (m_ownership == control_ownership)
00468     {Py_XINCREF(m_object);}
00469 }
00470 
00471 // Destructor decrements refcount if controlling ownership.
00472 // Always acquire the Python Global Interpreter Lock before decrementing.
00473 PythonObjectWrapper::~PythonObjectWrapper()
00474 {
00475     if (m_ownership == control_ownership) {
00476         // Hack: don't acquire the GIL if we are dealing with Py_None, since
00477         // this object never moves in memory (no deallocation) and decrementing
00478         // its refcount should be thread-safe.  It is possible that some empty
00479         // PythonObjectWrappers exist without build() having been called on
00480         // them (e.g. type registration for plearn help), i.e. Py_Initialize()
00481         // has not been called and acquiring the GIL in those cases is iffy.
00482         if (m_object == Py_None)
00483             Py_XDECREF(m_object);
00484         else {
00485             PythonGlobalInterpreterLock gil;
00486             Py_XDECREF(m_object);
00487         }
00488     }
00489 }
00490 
00491 // Assignment: let copy ctor and dtor take care of ownership
00492 PythonObjectWrapper& PythonObjectWrapper::operator=(const PythonObjectWrapper& rhs)
00493 {
00494     if (&rhs != this) {
00495         PythonObjectWrapper other(rhs);
00496         swap(other);
00497     }
00498     return *this;
00499 }
00500 
00501 // Swap *this with another instance
00502 void PythonObjectWrapper::swap(PythonObjectWrapper& other)
00503 {
00504     std::swap(this->m_ownership, other.m_ownership);
00505     std::swap(this->m_object,    other.m_object);
00506 }
00507 
00508 // Print out the Python object to stderr for debugging purposes
00509 void PythonObjectWrapper::printDebug() const
00510 {
00511     PyObject_Print(m_object, stderr, Py_PRINT_RAW);
00512 }
00513 
00514 bool PythonObjectWrapper::isNull() const
00515 {
00516     return ! m_object || m_object == Py_None;
00517 }
00518 
00519 
00520 //##### Trampoline ############################################################
00521 PyObject* PythonObjectWrapper::trampoline(PyObject* self, PyObject* args)
00522 {
00523 //     DBG_MODULE_LOG << "PythonObjectWrapper::trampoline(" << PythonObjectWrapper(self)
00524 //                    << ", " << PythonObjectWrapper(args) << ')' << endl;
00525     PythonGlobalInterpreterLock gil;         // For thread-safety
00526 
00527     //get object and trampoline from self
00528     PythonObjectWrapper s(self);
00529 
00530     //perr << "refcnt self= " << self->ob_refcnt << endl;
00531 
00532     RemoteTrampoline* tramp=
00533         dynamic_cast<RemoteTrampoline*>(s.as<PPointable*>());
00534     if(!tramp)
00535         PLERROR("in PythonObjectWrapper::trampoline : "
00536                 "can't unwrap RemoteTrampoline.");
00537 
00538     //wrap args
00539     int size = PyTuple_GET_SIZE(args);
00540     TVec<PythonObjectWrapper> args_tvec(size);
00541     for(int i= 0; i < size; ++i)
00542         args_tvec[i]=
00543             PythonObjectWrapper(PyTuple_GET_ITEM(args,i));
00544 
00545     // separate self from other params.
00546     Object* obj= args_tvec[0];
00547     args_tvec.subVecSelf(1, args_tvec.size()-1);
00548 
00549     //perr << "REMOTE METHOD: " << obj->classname() << "::" << tramp->documentation().name() << endl;
00550 
00551     gc_collect1();
00552 
00553     //call, catch and send any errors to python
00554     try
00555     {
00556         PythonObjectWrapper returned_value= tramp->call(obj, args_tvec);
00557         PyObject* to_return= returned_value.getPyObject();
00558         Py_XINCREF(to_return);
00559         return to_return;
00560     }
00561     catch(const PLearnError& e)
00562     {
00563         PyErr_SetString(the_PLearn_python_exception, e.message().c_str());
00564         return 0;
00565     }
00566     catch(const std::exception& e)
00567     {
00568         PyErr_SetString(PyExc_Exception, e.what());
00569         return 0;
00570     }
00571     catch(...)
00572     {
00573         PyErr_SetString(PyExc_Exception,
00574                         "Caught unknown C++ exception while executing injected function "
00575                         "inside a PythonObjectWrapper");
00576         return 0;
00577     }
00578 }
00579 
00580 
00581 void checkWrappedObjects(const string& msg)
00582 {
00583     DBG_MODULE_LOG << msg << endl;
00584     map<PyObject*, const Object*> rev_map;
00585     for(PythonObjectWrapper::wrapped_objects_t::iterator it= PythonObjectWrapper::m_wrapped_objects.begin();
00586         it != PythonObjectWrapper::m_wrapped_objects.end(); ++it)
00587     {
00588         DBG_MODULE_LOG << "checking:" << (void*)it->first << " -> " << (void*)it->second << endl;
00589         map<PyObject*, const Object*>::iterator jt= rev_map.find(it->second);
00590         DBG_MODULE_LOG.clearInOutMaps();
00591         if(jt != rev_map.end())
00592             DBG_MODULE_LOG << "*** ALREADY IN MAP:" << it->second << "w/" << it->first << " ; now " << jt->second << endl;
00593         //else
00594         rev_map[it->second]= it->first;
00595     }
00596     DBG_MODULE_LOG << "FINISHED checking wrapped objects:\t" << rev_map.size() << '\t' << msg << endl;
00597 }
00598 
00599 
00600 PyObject* PythonObjectWrapper::python_del(PyObject* self, PyObject* args)
00601 {
00602     TVec<PyObject*> args_tvec=
00603         PythonObjectWrapper(args).as<TVec<PyObject*> >();
00604 
00605     Object* obj= PythonObjectWrapper(args_tvec[0]);
00606 
00607     string classname= obj->classname();
00608     pypl_classes_t::iterator clit= m_pypl_classes.find(classname);
00609     if(clit == m_pypl_classes.end())
00610         PLERROR("in PythonObjectWrapper::python_del : "
00611                 "deleting obj. for which no python class exists!");
00612     --clit->second.nref;
00613 
00614     //perr << "delete " << (void*)obj << " : " << (void*)m_wrapped_objects[obj] << endl;
00615     //perr << "bef.del o->usage()= " << obj->usage() << endl;
00616     obj->unref();//python no longer references this obj.
00617     //perr << "aft.del o->usage()= " << obj->usage() << endl;
00618 
00619     //GC
00620     if(m_gc_next_object->first == obj)
00621         m_gc_next_object= m_wrapped_objects.end();
00622 
00623     m_wrapped_objects.erase(obj);
00624 
00625     //printWrappedObjects();
00626 
00627     return newPyObject();//None
00628 }
00629 
00630 PyObject* PythonObjectWrapper::newCPPObj(PyObject* self, PyObject* args)
00631 {
00632     TVec<PyObject*> args_tvec= 
00633         PythonObjectWrapper(args).as<TVec<PyObject*> >();
00634     Object* o= newObjectFromClassname(PyString_AsString(args_tvec[1]));
00635 
00636     //DBG_MODULE_LOG << "In PythonObjectWrapper::newCPPObj() " << PyString_AsString(args_tvec[1]) << " <-> " << (void*)o << '\t' << o << endl;
00637     //perr << "new o->usage()= " << o->usage() << endl;
00638 
00639     return PyCObject_FromVoidPtr(o, 0);
00640 }
00641 
00642 PyObject* PythonObjectWrapper::refCPPObj(PyObject* self, PyObject* args)
00643 {
00644     TVec<PyObject*> args_tvec= 
00645         PythonObjectWrapper(args).as<TVec<PyObject*> >();
00646     PyObject* pyo= args_tvec[1];
00647     Object* o= PythonObjectWrapper(pyo);
00648     if(args_tvec.length() < 3 || args_tvec[2]==Py_True)
00649         o->ref();
00650 
00651     //perr << "ref o->usage()= " << o->usage() << endl;
00652     PythonObjectWrapper::m_wrapped_objects[o]= pyo;
00653     //checkWrappedObjects(">>>>>>>>>> in refcppobj -> checkWrappedObjects");// debug only
00654     //perr << "refCPPObj: " << (void*)o << " : " << (void*)pyo << endl;
00655 
00656     //DBG_MODULE_LOG << "In PythonObjectWrapper::refCPPObj() " << PythonObjectWrapper(pyo) << " <-> " << (void*)o << '\t' << o << endl;
00657     addToWrappedObjectsSet(pyo);//Py_INCREF(pyo);
00658     
00659     //printWrappedObjects();///***///***
00660 
00661     return newPyObject();//None
00662 }
00663 
00664 void PythonObjectWrapper::gc_collect1()
00665 {
00666     DBG_MODULE_LOG << "entering PythonObjectWrapper::gc_collect1()" << endl;
00667 
00668     if(m_gc_next_object == m_wrapped_objects.end())
00669         m_gc_next_object= m_wrapped_objects.begin();
00670     if(m_gc_next_object != m_wrapped_objects.end())
00671     {
00672         wrapped_objects_t::iterator it= m_gc_next_object;
00673         ++m_gc_next_object;
00674         if(it->first->usage() == 1 && it->second->ob_refcnt == 1)
00675         {
00676             //Py_DECREF(it->second);
00677             DBG_MODULE_LOG.clearInOutMaps();
00678             PyObject* cptr= PyObject_GetAttrString(it->second, const_cast<char*>("_cptr"));
00679 //             DBG_MODULE_LOG << "In PythonObjectWrapper::gc_collect1(), removing object " 
00680 //                            << PythonObjectWrapper(it->second)
00681 //                            << " ; python version of: " << it->first << " (" << (void*)it->first 
00682 //                            << ", " << PyCObject_AsVoidPtr(cptr) << ')'
00683 //                            << endl;
00684             if(!cptr)
00685             {
00686                 if(PyErr_Occurred()) PyErr_Print();
00687                 PLERROR("In PythonObjectWrapper::gc_collect1 : cannot get attribute '_cptr' from Python object ");
00688             }
00689             Py_DECREF(cptr);
00690             removeFromWrappedObjectsSet(it->second);
00691             gc_collect1();
00692         }
00693     }
00694     DBG_MODULE_LOG << "exiting PythonObjectWrapper::gc_collect1()" << endl;
00695 }
00696 
00697 
00698 //#####  newPyObject  #########################################################
00699 
00701 PyObject* PythonObjectWrapper::newPyObject()
00702 {
00703     Py_XINCREF(Py_None);
00704     return Py_None;
00705 }
00706 
00707 PythonObjectWrapper::wrapped_objects_t
00708     PythonObjectWrapper::m_wrapped_objects;//init.
00709 
00710 PythonObjectWrapper::pypl_classes_t
00711     PythonObjectWrapper::m_pypl_classes;//init.
00712 //init.
00713 bool PythonObjectWrapper::m_unref_injected= false;
00714 PyMethodDef PythonObjectWrapper::m_unref_method_def;
00715 PyMethodDef PythonObjectWrapper::m_newCPPObj_method_def;
00716 PyMethodDef PythonObjectWrapper::m_refCPPObj_method_def;
00717 PythonObjectWrapper::wrapped_objects_t::iterator 
00718   PythonObjectWrapper::m_gc_next_object= 
00719   PythonObjectWrapper::m_wrapped_objects.end();
00720 
00721 PyObject* ConvertToPyObject<Object*>::newPyObject(const Object* x)
00722 {
00723 //     DBG_MODULE_LOG << "ENTER ConvertToPyObject<Object*>::newPyObject " 
00724 //                    << (void*)x << ' ' << (x?x->asString():"") << endl;
00725     // void ptr becomes None
00726     if(!x) return PythonObjectWrapper::newPyObject();
00727 
00728     PythonGlobalInterpreterLock gil;         // For thread-safety
00729     static PythonEmbedder embedder;
00730     PythonObjectWrapper::initializePython();
00731 
00732     //see if this obj. is already wrapped
00733     PythonObjectWrapper::wrapped_objects_t::iterator objit=
00734         PythonObjectWrapper::m_wrapped_objects.find(x);
00735     if(objit != PythonObjectWrapper::m_wrapped_objects.end())
00736     {
00737         PyObject* o= objit->second;
00738         Py_INCREF(o);//new ref
00739         return o;//return ptr to already created pyobj
00740     }
00741     // get ptr of object to wrap
00742     PyObject* plobj= PyCObject_FromVoidPtr(const_cast<Object*>(x), NULL);
00743 
00744     // try to find existing python class
00745     string classname= x->classname();
00746     PythonObjectWrapper::pypl_classes_t::iterator clit= 
00747         PythonObjectWrapper::m_pypl_classes.find(classname);
00748     if(clit == PythonObjectWrapper::m_pypl_classes.end())
00749         PLERROR("in ConvertToPyObject<Object*>::newPyObject : "
00750                 "cannot find python class %s",classname.c_str());
00751     PyObject* the_pyclass= clit->second.pyclass;
00752 
00753     //create the python object itself from the_pyclass
00754     PyObject* args= PyTuple_New(0);
00755     PyObject* params= PyDict_New();
00756     PyDict_SetItemString(params, "_cptr", plobj);
00757     Py_DECREF(plobj);
00758     PyObject* the_obj= PyObject_Call(the_pyclass, args, params);
00759     Py_DECREF(args);
00760     Py_DECREF(params);
00761     if(!the_obj)
00762     {
00763         if (PyErr_Occurred()) PyErr_Print();
00764         PLERROR("in PythonObjectWrapper::newPyObject : "
00765                 "can't construct a WrappedPLearnObject.");
00766     }
00767 
00768     // augment refcount since python now 'points' to this obj.
00769     x->ref();
00770 
00771     PythonObjectWrapper::m_wrapped_objects[x]= the_obj;
00772     //checkWrappedObjects(">>>>>>>>>> in newpyobj -> checkWrappedObjects"); // debug only
00773 
00774 //    perr << "newPyObject: " << (void*)x << " : " << (void*)the_obj << endl;
00775 
00776     addToWrappedObjectsSet(the_obj);//Py_INCREF(the_obj);
00777     //printWrappedObjects();
00778 //     DBG_MODULE_LOG << "EXIT ConvertToPyObject<Object*>::newPyObject " 
00779 //                    << (void*)x << ' ' << x->asString() << " => "
00780 //                    << (void*) the_obj << ' ' << PythonObjectWrapper(the_obj) << endl;
00781 
00782     return the_obj;
00783 }
00784 
00785 PyObject* ConvertToPyObject<bool>::newPyObject(const bool& x)
00786 {
00787     if (x) {
00788         Py_XINCREF(Py_True);
00789         return Py_True;
00790     }
00791     else {
00792         Py_XINCREF(Py_False);
00793         return Py_False;
00794     }
00795 }
00796 
00797 PyObject* ConvertToPyObject<double>::newPyObject(const double& x)
00798 {
00799     return PyFloat_FromDouble(x);
00800 }
00801 
00802 PyObject* ConvertToPyObject<float>::newPyObject(const float& x)
00803 {
00804     return PyFloat_FromDouble(double(x));
00805 }
00806 
00807 PyObject* ConvertToPyObject<char*>::newPyObject(const char* x)
00808 {
00809     return PyString_FromString(x);
00810 }
00811 
00812 PyObject* ConvertToPyObject<string>::newPyObject(const string& x)
00813 {
00814     return PyString_FromString(x.c_str());
00815 }
00816 
00817 PyObject* ConvertToPyObject<PPath>::newPyObject(const PPath& x)
00818 {
00819     return PyString_FromString(x.c_str());
00820 }
00821 
00822 
00823 PyObject* ConvertToPyObject<Vec>::newPyObject(const Vec& data)
00824 {
00825     PyArrayObject* pyarr = 0;
00826     if (data.isNull() || data.isEmpty())
00827         pyarr = NA_NewArray(NULL, tReal, 1, 0);
00828     else
00829         pyarr = NA_NewArray(data.data(), tReal, 1, data.size());
00830 
00831     return (PyObject*)pyarr;
00832 }
00833 
00834 PyObject* ConvertToPyObject<Mat>::newPyObject(const Mat& data)
00835 {
00836     PyArrayObject* pyarr = 0;
00837     if (data.isNull() || data.isEmpty())
00838         pyarr = NA_NewArray(NULL, tReal, 2, data.length(), data.width());
00839     else if (data.mod() == data.width())
00840         pyarr = NA_NewArray(data.data(), tReal, 2, data.length(),
00841                             data.width());
00842     else {
00843         // static PyObject* NA_NewAll( int ndim, maybelong *shape, NumarrayType
00844         // type, void *buffer, maybelong byteoffset, maybelong bytestride, int
00845         // byteorder, int aligned, int writable)
00846         //
00847         // numarray from C data buffer. The new array has type type, ndim
00848         // dimensions, and the length of each dimensions must be given in
00849         // shape[ndim]. byteoffset, bytestride specify the data-positions in
00850         // the C array to use. byteorder and aligned specify the corresponding
00851         // parameters. byteorder takes one of the values NUM_BIG_ENDIAN or
00852         // NUM_LITTLE_ENDIAN. writable defines whether the buffer object
00853         // associated with the resuling array is readonly or writable. Data is
00854         // copied from buffer into the memory object of the new array.
00855 
00856         // maybelong shape[2];
00857         // shape[0] = data.length();
00858         // shape[1] = data.width();
00859         // pyarr = NA_NewAll(2, shape, tReal, data.data(), 0,
00860         //                   data.mod()*sizeof(real), NA_ByteOrder(), 1, 1);
00861 
00862         // NOTE (NC) -- I could not get the above function to work; for now,
00863         // simply copy the matrix to new storage before converting to Python.
00864         Mat new_data = data.copy();
00865         pyarr = NA_NewArray(new_data.data(), tReal, 2,
00866                             new_data.length(), new_data.width());
00867     }
00868 
00869     return (PyObject*)pyarr;
00870 }
00871 
00872 
00873 bool PythonObjectWrapper::VMatAsPtr= false;//numpy array by default
00874 
00875 //PyObject* ConvertToPyObject<VMat>::newPyObject(const VMat& vm)
00876 PyObject* ConvertToPyObject<PP<VMatrix> >::newPyObject(const PP<VMatrix>& vm)
00877 {
00878     if(PythonObjectWrapper::VMatAsPtr)
00879         return ConvertToPyObject<Object*>::newPyObject(static_cast<Object*>(vm));
00880     else// as a numpy array
00881         if (vm.isNull())
00882             return ConvertToPyObject<Mat>::newPyObject(Mat());
00883         else
00884             return ConvertToPyObject<Mat>::newPyObject(vm->toMat());
00885 }
00886 
00887 PyObject* ConvertToPyObject<PythonObjectWrapper>::newPyObject(const PythonObjectWrapper& pow)
00888 {
00889     Py_XINCREF(pow.m_object);
00890     return pow.m_object;
00891 }
00892 
00893 PyObject* ConvertToPyObject<CopiesMap>::newPyObject(const CopiesMap& copies)
00894 {
00895     PyObject* pyobj= PyDict_New();
00896     for(CopiesMap::const_iterator it= copies.begin();
00897         it != copies.end(); ++it)
00898     {
00899         PyObject* key= PyCObject_FromVoidPtr(const_cast<void*>(it->first), 0);
00900         PyObject* val= PyCObject_FromVoidPtr(it->second, 0);
00901         int non_success = PyDict_SetItem(pyobj, key, val);
00902         Py_XDECREF(key);
00903         Py_XDECREF(val);
00904         if(non_success)
00905             PLERROR("ConvertToPyObject<CopiesMap>::newPyObject: cannot insert element "
00906                     "into Python dict");
00907     }
00908     return pyobj;
00909 }
00910 
00911 PyObject* ConvertToPyObject<VarArray>::newPyObject(const VarArray& var)
00912 {
00913     return ConvertToPyObject<TVec<Var> >::newPyObject(var);
00914 }
00915 
00916 PyObject* ConvertToPyObject<RealRange>::newPyObject(const RealRange& rr)
00917 {
00918     string pycode= "\nfrom plearn.pybridge.wrapped_plearn_object import RealRange\n";
00919     pycode+= string("\nresult= RealRange(leftbracket='") + rr.leftbracket + "', "
00920         + "low= " + tostring(rr.low) + ", high= " + tostring(rr.high) + ", "
00921         + "rightbracket= '" + rr.rightbracket + "')\n";
00922     PyObject* env= PyDict_New();
00923     if(0 != PyDict_SetItemString(env, "__builtins__", PyEval_GetBuiltins()))
00924         PLERROR("in ConvertToPyObject<RealRange>::newPyObject : "
00925                 "cannot insert builtins in env.");
00926     PyObject* res= PyRun_String(pycode.c_str(), Py_file_input, env, env);
00927     if(!res)
00928     {
00929         Py_DECREF(env);
00930         if(PyErr_Occurred()) PyErr_Print();
00931         PLERROR("in ConvertToPyObject<RealRange>::newPyObject : "
00932                 "cannot convert to a RealRange.");
00933     }
00934     Py_DECREF(res);
00935     PyObject* py_rr= PythonObjectWrapper(env).as<std::map<string, PyObject*> >()["result"];
00936     Py_INCREF(py_rr);
00937     Py_DECREF(env);
00938     return py_rr;
00939 }
00940 
00941 PyObject* ConvertToPyObject<VMField>::newPyObject(const VMField& vmf)
00942 {
00943     string pycode = "\nfrom plearn.pybridge.wrapped_plearn_object import VMField\n";
00944     pycode += string("\nresult = VMField(name='") + vmf.name + "', " + "fieldtype=" + tostring(vmf.fieldtype) + ")\n";
00945 
00946     PyObject* env = PyDict_New();
00947     if (0 != PyDict_SetItemString(env, "__builtins__", PyEval_GetBuiltins()))
00948         PLERROR("In ConvertToPyObject<VMField>::newPyObject : cannot insert builtins in env.");
00949     PyObject* res = PyRun_String(pycode.c_str(), Py_file_input, env, env);
00950     if (!res)
00951     {
00952         Py_DECREF(env);
00953         if (PyErr_Occurred()) PyErr_Print();
00954         PLERROR("In ConvertToPyObject<VMField>::newPyObject : cannot convert to a VMField.");
00955     }
00956     Py_DECREF(res);
00957     PyObject* py_vmf = PythonObjectWrapper(env).as<std::map<string, PyObject*> >()["result"];
00958     Py_INCREF(py_vmf);
00959     Py_DECREF(env);
00960     return py_vmf;
00961 }
00962 
00963 PStream& operator>>(PStream& in, PythonObjectWrapper& v)
00964 {
00965     PLERROR("operator>>(PStream&, PythonObjectWrapper&) : "
00966             "not supported (yet).");
00967 /*
00968     string s;
00969     in >> s;
00970     string sub= "PythonObjectWrapper(ownership=";
00971     if(s.substr(0,sub.length()) != sub)
00972         PLERROR("in operator>>(PStream& in, PythonObjectWrapper& v) : "
00973                 "expected '%s' but got '%s'.",
00974                 sub.c_str(), s.c_str());
00975     s= s.substr(sub.length());
00976     v.m_ownership= static_cast<PythonObjectWrapper::OwnershipMode>(s[0]-'0');
00977     s= s.substr(1);
00978     sub= ", object=";
00979     if(s.substr(0,sub.length()) != sub)
00980         PLERROR("in operator>>(PStream& in, PythonObjectWrapper& v) : "
00981                 "expected '%s' but got '%s'.",
00982                 sub.c_str(), s.c_str());
00983     s= s.substr(sub.length());
00984     PStream sin= openString(s, PStream::plearn_ascii, "r");
00985     string pickle;
00986     sin >> pickle;
00987 
00988     PyObject* pypickle= PyString_FromString(pickle.c_str());
00989     PyObject* env= PyDict_New();
00990     if(0 != PyDict_SetItemString(env, "__builtins__", PyEval_GetBuiltins()))
00991         PLERROR("in operator>>(PStream&, PythonObjectWrapper& v) : "
00992                 "cannot insert builtins in env.");
00993     if(0 != PyDict_SetItemString(env, "the_pickle", pypickle))
00994         PLERROR("in operator>>(PStream&, PythonObjectWrapper& v) : "
00995                 "cannot insert the_pickle in env.");
00996     Py_DECREF(pypickle);
00997     PyObject* res= PyRun_String("\nfrom cPickle import *\nresult= loads(the_pickle)\n", 
00998                                 Py_file_input, env, env);
00999     if(!res)
01000     {
01001         Py_DECREF(env);
01002         if(PyErr_Occurred()) PyErr_Print();
01003         PLERROR("in operator<<(PStream&, const PythonObjectWrapper& v) : "
01004                 "cannot unpickle python object '%s'.",pickle.c_str());
01005     }
01006     Py_DECREF(res);
01007     v.m_object= 
01008         PythonObjectWrapper(env).as<std::map<string, PyObject*> >()["result"];
01009     Py_INCREF(v.m_object);
01010     Py_DECREF(env);
01011 */
01012     return in;
01013 }
01014 
01015 PStream& operator<<(PStream& out, const PythonObjectWrapper& v)
01016 {
01017     out << v.getPyObject();
01018     return out;
01019 
01020     PLERROR("operator<<(PStream&, const PythonObjectWrapper&) : "
01021             "not supported (yet).");
01022 /*
01023     PyObject* env= PyDict_New();
01024     if(0 != PyDict_SetItemString(env, "__builtins__", PyEval_GetBuiltins()))
01025         PLERROR("in operator<<(PStream&, const PythonObjectWrapper& v) : "
01026                 "cannot insert builtins in env.");
01027     if(0 != PyDict_SetItemString(env, "the_obj", v.m_object))
01028         PLERROR("in operator<<(PStream&, const PythonObjectWrapper& v) : "
01029                 "cannot insert the_obj in env.");
01030     PyObject* res= PyRun_String("\nfrom cPickle import *\nresult= dumps(the_obj)\n", 
01031                                 Py_file_input, env, env);
01032     if(!res)
01033     {
01034         Py_DECREF(env);
01035         if(PyErr_Occurred()) PyErr_Print();
01036         PLERROR("in operator<<(PStream&, const PythonObjectWrapper& v) : "
01037                 "cannot pickle python object.");
01038     }
01039     Py_DECREF(res);
01040     string pickle= 
01041         PythonObjectWrapper(env).as<std::map<string, PythonObjectWrapper> >()["result"];
01042         Py_DECREF(env);
01043     string toout= string("PythonObjectWrapper(ownership=") + tostring(v.m_ownership) + ", object=\"" + pickle + "\")";
01044     out << toout;
01045 */
01046     return out; // shut up compiler
01047 }
01048 
01049 
01050 PStream& operator>>(PStream& in, PyObject* v)
01051 {
01052     PLERROR("operator>>(PStream& in, PyObject* v) not supported yet");
01053     return in;
01054 }
01055 
01056 PStream& operator<<(PStream& out, const PyObject* v)
01057 {
01058     PyObject* pystr= PyObject_Str(const_cast<PyObject*>(v));
01059     if(!pystr)
01060     {
01061         if (PyErr_Occurred()) PyErr_Print();
01062         PLERROR("in PythonTableVMatrix::build_ : "
01063                 "access to underlying table's 'weightsize' failed.");
01064     }
01065     out << PythonObjectWrapper(pystr).as<string>();
01066     Py_DECREF(pystr);
01067     return out;
01068 }
01069 
01070 
01072 void printWrappedObjects()
01073 {
01074     //checkWrappedObjects(">>>>>>>>>> in printwrappedobjs -> checkWrappedObjects"); // debug only
01075 
01076     DBG_MODULE_LOG << "the_PLearn_python_module= " << (void*)the_PLearn_python_module << endl;
01077 
01078     perr << "wrapped_objects= " << endl;
01079     for(PythonObjectWrapper::wrapped_objects_t::iterator it= 
01080             PythonObjectWrapper::m_wrapped_objects.begin();
01081         it != PythonObjectWrapper::m_wrapped_objects.end(); ++it)
01082         perr << '\t' << it->first->classname() << ' ' << (void*)it->first 
01083              << ' ' << it->first->usage() << " : " 
01084              << (void*)it->second << ' ' << it->second->ob_refcnt << endl;
01085 }
01086 
01087 void ramassePoubelles()
01088 {
01089     DBG_MODULE_LOG << "entering ramassePoubelles" << endl;
01090     size_t sz= 0;
01091     while(sz != PythonObjectWrapper::m_wrapped_objects.size())
01092     {
01093         sz= PythonObjectWrapper::m_wrapped_objects.size();
01094         PythonObjectWrapper::wrapped_objects_t::iterator it= 
01095             PythonObjectWrapper::m_wrapped_objects.begin();
01096         while(it != PythonObjectWrapper::m_wrapped_objects.end())
01097         {
01098             PythonObjectWrapper::wrapped_objects_t::iterator jt= it;
01099             ++it;
01100             if(jt->second->ob_refcnt == 1 && jt->first->usage() == 1)
01101             {
01102                 DBG_MODULE_LOG << "In ramassePoubelles, removing object" << PythonObjectWrapper(jt->second) << endl;
01103                 removeFromWrappedObjectsSet(jt->second);
01104             }
01105         }
01106     }
01107     DBG_MODULE_LOG << "exiting ramassePoubelles" << endl;
01108 }
01109 
01110 
01111 bool getVMatAsPtr()
01112 {
01113     return PythonObjectWrapper::VMatAsPtr;
01114 }
01115 bool setVMatAsPtr(bool vmat_as_ptr)
01116 {
01117     bool prev= PythonObjectWrapper::VMatAsPtr;
01118     PythonObjectWrapper::VMatAsPtr= vmat_as_ptr;
01119     return prev;
01120 }
01121 
01122 
01123 BEGIN_DECLARE_REMOTE_FUNCTIONS
01124     declareFunction("printWrappedObjects", &printWrappedObjects,
01125                     (BodyDoc("Prints PLearn objects wrapped into python.\n")));
01126     declareFunction("ramassePoubelles", &ramassePoubelles,
01127                     (BodyDoc("GC for wrapped objects.\n")));
01128 
01129     declareFunction("getVMatAsPtr", &getVMatAsPtr,
01130                     (BodyDoc("Returns current setting of 'VMatAsPtr'.\n"
01131                              "true= wrapped VMat; false= numpy array.\n"),
01132                      RetDoc("current VMatAsPtr")));
01133     declareFunction("setVMatAsPtr", &setVMatAsPtr,
01134                     (BodyDoc("Sets 'VMatAsPtr', returns previous setting.\n"
01135                              "true= wrapped VMat; false= numpy array.\n"),
01136                      ArgDoc("vmat_as_ptr","wrap VMats instead of converting to numpy?"),
01137                      RetDoc("Previous setting")));
01138 END_DECLARE_REMOTE_FUNCTIONS
01139 
01140 
01141 
01142 } // end of namespace PLearn
01143 
01144 
01145 /*
01146   Local Variables:
01147   mode:c++
01148   c-basic-offset:4
01149   c-file-style:"stroustrup"
01150   c-file-offsets:((innamespace . 0)(inline-open . 0))
01151   indent-tabs-mode:nil
01152   fill-column:79
01153   End:
01154 */
01155 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines