PLearn 0.1
|
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 :