PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PythonObjectWrapper.h 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 00045 #ifndef PythonObjectWrapper_INC 00046 #define PythonObjectWrapper_INC 00047 00048 // Python stuff must be included first 00049 #include <plearn/python/PythonIncludes.h> 00050 00051 // From C++ stdlib 00052 #include <utility> // Pairs 00053 #include <vector> // vector<T> 00054 #include <map> // map<T,U> 00055 #include <set> // set<T> 00056 #include <limits> // numeric_limits<I> 00057 00058 // From PLearn 00059 #include <plearn/math/TVec.h> 00060 #include <plearn/math/TMat.h> 00061 #include <plearn/base/tostring.h> 00062 #include <plearn/base/PMemPool.h> 00063 #include <plearn/base/TypeTraits.h> 00064 #include <plearn/base/tuple.h> 00065 #include <plearn/base/CopiesMap.h> 00066 00067 // from boost 00068 #include <boost/static_assert.hpp> 00069 #include <boost/type_traits.hpp> 00070 00071 00072 #ifdef USEFLOAT 00073 #define PL_NPY_REAL NPY_FLOAT 00074 #define tReal tFloat32 00075 #else 00076 #define PL_NPY_REAL NPY_DOUBLE 00077 #define tReal tFloat64 00078 #endif 00079 00080 namespace PLearn { 00081 00082 class PythonObjectWrapper; // Forward-declare 00083 class Object; 00084 class VMatrix; 00085 class VarArray; 00086 class RealRange; 00087 class VMField; 00088 00091 void PLPythonConversionError(const char* function_name, PyObject* pyobj, 00092 bool print_traceback); 00093 00098 template <class I> 00099 I integerFromPyObject(PyObject* pyobj, bool print_traceback) 00100 { 00101 PLASSERT( pyobj ); 00102 00103 I result = (I) 0; 00104 if (PyInt_Check(pyobj)) 00105 { 00106 // pyobj is represented in Python as a long, 00107 // so we are sure it fits into a long, no need to check. 00108 long x = PyInt_AS_LONG(pyobj); 00109 result = static_cast<I>(x); 00110 00111 // Check if x fits into type I (overflow or sign problem) 00112 #ifdef __INTEL_COMPILER 00113 #pragma warning(disable:1682) 00114 // Yes, I know that "implicit conversion of a 64-bit integral type to a smaller 00115 // integral type (potential portability problem)", but the conversion is 00116 // explicit here. 00117 #endif 00118 if (static_cast<long>(result) != x 00119 || (!(numeric_limits<I>::is_signed) && x<0)) 00120 { 00121 PLPythonConversionError("integerFromPyObject<I>", pyobj, 00122 print_traceback); 00123 } 00124 #ifdef __INTEL_COMPILER 00125 #pragma warning(default:1682) 00126 #endif 00127 } 00128 else if (PyLong_Check(pyobj)) 00129 { 00130 if (numeric_limits<I>::is_signed) 00131 { 00132 // If I is signed, we have to accept negative values, so we use a 00133 // signed long long to hold the result. 00134 // No signed type can hold values greater than a long long anyway. 00135 long long x = PyLong_AsLongLong(pyobj); 00136 00137 // Check for possible overflow during conversion 00138 if (!PyErr_Occurred()) 00139 { 00140 #ifdef __INTEL_COMPILER 00141 #pragma warning(disable:1682) 00142 // Yes, I know that "implicit conversion of a 64-bit integral type to a smaller 00143 // integral type (potential portability problem)", but the conversion is 00144 // explicit here. 00145 #endif 00146 result = static_cast<I>(x); 00147 #ifdef __INTEL_COMPILER 00148 #pragma warning(default:1682) 00149 #endif 00150 00151 // Check if x fits into type I (overflow only, there 00152 // cannot be any sign error because I is signed, too) 00153 if (static_cast<long long>(result) != x) 00154 { 00155 PLPythonConversionError("integerFromPyObject<I>", pyobj, 00156 print_traceback); 00157 } 00158 } 00159 else if (PyErr_ExceptionMatches(PyExc_OverflowError)) 00160 { 00161 PyErr_Clear(); 00162 PLPythonConversionError("integerFromPyObject<I>", pyobj, 00163 print_traceback); 00164 } 00165 // else? 00166 } 00167 else 00168 { 00169 // I is unsigned 00170 unsigned long long x = PyLong_AsUnsignedLongLong(pyobj); 00171 00172 // Check for possible overflow during conversion 00173 if (!PyErr_Occurred()) 00174 { 00175 #ifdef __INTEL_COMPILER 00176 #pragma warning(disable:1682) 00177 // Yes, I know that "implicit conversion of a 64-bit integral type to a smaller 00178 // integral type (potential portability problem)", but the conversion is 00179 // explicit here. 00180 #endif 00181 result = static_cast<I>(x); 00182 #ifdef __INTEL_COMPILER 00183 #pragma warning(default:1682) 00184 #endif 00185 00186 // Check if x fits into type I (overflow only) 00187 if (static_cast<unsigned long long>(result) != x) 00188 { 00189 PLPythonConversionError("integerFromPyObject<I>", pyobj, 00190 print_traceback); 00191 } 00192 } 00193 else if (PyErr_ExceptionMatches(PyExc_OverflowError) // too big 00194 || PyErr_ExceptionMatches(PyExc_TypeError)) // negative 00195 { 00196 PyErr_Clear(); 00197 PLPythonConversionError("integerFromPyObject<I>", pyobj, 00198 print_traceback); 00199 } 00200 // else? 00201 } 00202 } 00203 else 00204 PLPythonConversionError("integerFromPyObject<I>", pyobj, 00205 print_traceback); 00206 return result; 00207 } 00208 00209 00210 //##### ConvertFromPyObject ################################################# 00211 00225 template <class T> 00226 struct ConvertFromPyObject 00227 { 00228 static T convert(PyObject* x, bool print_traceback); 00229 }; 00230 00231 template <> 00232 struct ConvertFromPyObject<PyObject*> 00233 { 00234 //trivial: no conversion 00235 static PyObject* convert(PyObject*, bool print_traceback); 00236 }; 00237 00238 template <> 00239 struct ConvertFromPyObject<bool> 00240 { 00241 static bool convert(PyObject*, bool print_traceback); 00242 }; 00243 00244 template <> 00245 struct ConvertFromPyObject<short> 00246 { 00247 static short convert(PyObject* pyobj, bool print_traceback) 00248 { return integerFromPyObject<short>(pyobj, print_traceback); } 00249 }; 00250 00251 template <> 00252 struct ConvertFromPyObject<unsigned short> 00253 { 00254 static unsigned short convert(PyObject* pyobj, bool print_traceback) 00255 { return integerFromPyObject<unsigned short>(pyobj, print_traceback); } 00256 }; 00257 00258 template <> 00259 struct ConvertFromPyObject<int> 00260 { 00261 static int convert(PyObject* pyobj, bool print_traceback) 00262 { return integerFromPyObject<int>(pyobj, print_traceback); } 00263 }; 00264 00265 template <> 00266 struct ConvertFromPyObject<unsigned int> 00267 { 00268 static unsigned int convert(PyObject* pyobj, bool print_traceback) 00269 { return integerFromPyObject<unsigned int>(pyobj, print_traceback); } 00270 }; 00271 00272 template <> 00273 struct ConvertFromPyObject<long> 00274 { 00275 static long convert(PyObject* pyobj, bool print_traceback) 00276 { return integerFromPyObject<long>(pyobj, print_traceback); } 00277 }; 00278 00279 template <> 00280 struct ConvertFromPyObject<unsigned long> 00281 { 00282 static unsigned long convert(PyObject* pyobj, bool print_traceback) 00283 { return integerFromPyObject<unsigned long>(pyobj, print_traceback); } 00284 }; 00285 00286 template <> 00287 struct ConvertFromPyObject<long long> 00288 { 00289 static long long convert(PyObject* pyobj, bool print_traceback) 00290 { return integerFromPyObject<long long>(pyobj, print_traceback); } 00291 }; 00292 00293 template <> 00294 struct ConvertFromPyObject<unsigned long long> 00295 { 00296 static unsigned long long convert(PyObject* pyobj, bool print_traceback) 00297 { return integerFromPyObject<unsigned long long>(pyobj, print_traceback); } 00298 }; 00299 00300 00301 template <> 00302 struct ConvertFromPyObject<double> 00303 { 00304 static double convert(PyObject*, bool print_traceback); 00305 }; 00306 00307 template <> 00308 struct ConvertFromPyObject<float> 00309 { 00310 static float convert(PyObject*, bool print_traceback); 00311 }; 00312 00313 template <> 00314 struct ConvertFromPyObject<string> 00315 { 00316 static string convert(PyObject*, bool print_traceback); 00317 }; 00318 00319 00320 template <> 00321 struct ConvertFromPyObject<PPath> 00322 { 00323 static PPath convert(PyObject*, bool print_traceback); 00324 }; 00325 00326 00327 template <> 00328 struct ConvertFromPyObject<PPointable*> 00329 { 00330 static PPointable* convert(PyObject*, bool print_traceback); 00331 }; 00332 00333 template <> 00334 struct ConvertFromPyObject<Object*> 00335 { 00336 static Object* convert(PyObject*, bool print_traceback); 00337 }; 00338 00340 // PARTIAL specialisation from T*. Assume Object*. 00341 // todo: fix this assumption 00342 template <class T> 00343 struct ConvertFromPyObject<T*> 00344 { 00345 static T* convert(PyObject* pyobj, bool print_traceback) 00346 { 00347 // Compile-time assertion: 00348 BOOST_STATIC_ASSERT((boost::is_base_of<Object, typename boost::remove_cv<T>::type>::value) 00349 || (boost::is_same<Object, typename boost::remove_cv<T>::type>::value)); 00350 //N.B.: If this assertion fails, it probably means that you are trying 00351 // to retrieve a pointer to something that is not an Object from 00352 // python. Only Object pointers are supported. 00353 00354 Object* obj = ConvertFromPyObject<Object*>::convert(pyobj, 00355 print_traceback); 00356 if (T* tobj = dynamic_cast<T*>(obj)) 00357 return tobj; 00358 else 00359 PLERROR("Cannot convert object from python (type='%s').", 00360 TypeTraits<T*>::name().c_str()); 00361 return 0; // Silence compiler 00362 } 00363 }; 00365 00366 template <> 00367 struct ConvertFromPyObject<Vec> 00368 { 00369 // Return fresh storage 00370 static Vec convert(PyObject*, bool print_traceback); 00371 00372 // Convert into pre-allocated Vec; resize it if necessary 00373 static void convert(PyObject* pyobj, Vec& result, 00374 bool print_traceback); 00375 }; 00376 00377 template <> 00378 struct ConvertFromPyObject<Mat> 00379 { 00380 // Return fresh storage 00381 static Mat convert(PyObject*, bool print_traceback=true); 00382 00383 // Convert into pre-allocated Vec; resize it if necessary 00384 static void convert(PyObject* pyobj, Mat& result, 00385 bool print_traceback); 00386 }; 00387 00388 template <> 00389 struct ConvertFromPyObject<PP<VMatrix> > 00390 { 00391 // Return new MemoryVMatrix 00392 static PP<VMatrix> convert(PyObject*, bool print_traceback); 00393 }; 00394 00395 template <> 00396 struct ConvertFromPyObject<PythonObjectWrapper> 00397 { 00398 static PythonObjectWrapper convert(PyObject*, bool print_traceback); 00399 }; 00400 00401 00402 template <typename T> 00403 struct ConvertFromPyObject<PP<T> > 00404 { 00405 static PP<T> convert(PyObject*, bool print_traceback); 00406 }; 00407 00408 template <class T> 00409 struct ConvertFromPyObject< TVec<T> > 00410 { 00411 static TVec<T> convert(PyObject*, bool print_traceback); 00412 }; 00413 00414 template <class T> 00415 struct ConvertFromPyObject< Array<T> > 00416 { 00417 static Array<T> convert(PyObject*, bool print_traceback); 00418 }; 00419 00420 template <class T> 00421 struct ConvertFromPyObject<TMat<T> > 00422 { 00423 static TMat<T> convert(PyObject*, bool print_traceback); 00424 }; 00425 00426 template <class T> 00427 struct ConvertFromPyObject< std::vector<T> > 00428 { 00429 static std::vector<T> convert(PyObject*, bool print_traceback); 00430 }; 00431 00432 template <class T, class U> 00433 struct ConvertFromPyObject< std::map<T,U> > 00434 { 00435 static std::map<T,U> convert(PyObject*, bool print_traceback); 00436 }; 00437 00438 template <class T> 00439 struct ConvertFromPyObject<std::set<T> > 00440 { 00441 static std::set<T> convert(PyObject*, bool print_traceback); 00442 }; 00443 00444 template <class T, class U> 00445 struct ConvertFromPyObject< std::pair<T,U> > 00446 { 00447 static std::pair<T,U> convert(PyObject*, bool print_traceback); 00448 }; 00449 00450 template <> 00451 struct ConvertFromPyObject<CopiesMap> 00452 { 00453 static CopiesMap convert(PyObject*, bool print_traceback); 00454 }; 00455 00456 template <> 00457 struct ConvertFromPyObject<VarArray> 00458 { 00459 static VarArray convert(PyObject*, bool print_traceback); 00460 }; 00461 00462 template <> 00463 struct ConvertFromPyObject<RealRange> 00464 { 00465 static RealRange convert(PyObject*, bool print_traceback); 00466 }; 00467 00468 template <> 00469 struct ConvertFromPyObject<VMField> 00470 { 00471 static VMField convert(PyObject*, bool print_traceback); 00472 }; 00473 00474 /***** 00475 * Equivalence of types C++ -> numpy 00476 */ 00477 template <typename T> 00478 int numpyType() 00479 { 00480 PLERROR("in numpyType: no numpy equivalent to C++ type %s", 00481 TypeTraits<T*>::name().c_str()); 00482 return -1; //shut up compiler 00483 } 00484 00485 template<> int numpyType<bool>(); 00486 template<> int numpyType<signed char>(); 00487 template<> int numpyType<unsigned char>(); 00488 template<> int numpyType<signed short>(); 00489 template<> int numpyType<unsigned short>(); 00490 template<> int numpyType<signed int>(); 00491 template<> int numpyType<unsigned int>(); 00492 template<> int numpyType<signed long>(); 00493 template<> int numpyType<unsigned long>(); 00494 template<> int numpyType<signed long long>(); 00495 template<> int numpyType<unsigned long long>(); 00496 template<> int numpyType<float>(); 00497 template<> int numpyType<double>(); 00498 template<> int numpyType<long double>(); 00499 00500 00502 template <class I> 00503 PyObject* integerToPyObject(const I& x) 00504 { 00505 // Try to convert x to a long 00506 #ifdef __INTEL_COMPILER 00507 #pragma warning(disable:1682) 00508 // Yes, I know that "implicit conversion of a 64-bit integral type to a smaller 00509 // integral type (potential portability problem)", but the conversion is 00510 // explicit here. 00511 #endif 00512 long y = static_cast<long>(x); 00513 #ifdef __INTEL_COMPILER 00514 #pragma warning(default:1682) 00515 #endif 00516 00517 // Check if we lost value information or sign 00518 if (static_cast<I>(y) == x && (numeric_limits<I>::is_signed || y >= 0)) 00519 return PyInt_FromLong(y); 00520 else if (numeric_limits<I>::is_signed) 00521 return PyLong_FromLongLong(static_cast<long long>(x)); 00522 else 00523 return PyLong_FromUnsignedLongLong(static_cast<unsigned long long>(x)); 00524 } 00525 00527 // ConvertToPyObject<> 00528 // Conversions from PLearn to Python 00529 template<typename T> 00530 struct ConvertToPyObject 00531 { 00532 static PyObject* newPyObject(const T& x); 00533 }; 00534 00535 // Specialization for Object* 00536 template<> struct ConvertToPyObject<Object*> 00537 { static PyObject* newPyObject(const Object* x); }; 00538 00540 // Other specializations 00542 00543 template<> struct ConvertToPyObject<bool> 00544 { static PyObject* newPyObject(const bool& x); }; 00545 00546 template<> struct ConvertToPyObject<short> 00547 { 00548 static PyObject* newPyObject(const short& x) 00549 { return integerToPyObject(x); } 00550 }; 00551 00552 template<> struct ConvertToPyObject<unsigned short> 00553 { 00554 static PyObject* newPyObject(const unsigned short& x) 00555 { return integerToPyObject(x); } 00556 }; 00557 00558 template<> struct ConvertToPyObject<int> 00559 { 00560 static PyObject* newPyObject(const int& x) 00561 { return integerToPyObject(x); } 00562 }; 00563 00564 template<> struct ConvertToPyObject<unsigned int> 00565 { 00566 static PyObject* newPyObject(const unsigned int& x) 00567 { return integerToPyObject(x); } 00568 }; 00569 00570 template<> struct ConvertToPyObject<long> 00571 { 00572 static PyObject* newPyObject(const long& x) 00573 { return integerToPyObject(x); } 00574 }; 00575 00576 template<> struct ConvertToPyObject<unsigned long> 00577 { 00578 static PyObject* newPyObject(const unsigned long& x) 00579 { return integerToPyObject(x); } 00580 }; 00581 00582 template<> struct ConvertToPyObject<long long> 00583 { 00584 static PyObject* newPyObject(const long long& x) 00585 { return integerToPyObject(x); } 00586 }; 00587 00588 template<> struct ConvertToPyObject<unsigned long long> 00589 { 00590 static PyObject* newPyObject(const unsigned long long& x) 00591 { return integerToPyObject(x); } 00592 }; 00593 00594 /* 00595 template<> struct ConvertToPyObject<int64_t> 00596 { static PyObject* newPyObject(const int64_t& x); }; 00597 template<> struct ConvertToPyObject<uint64_t> 00598 { static PyObject* newPyObject(const uint64_t& x); }; 00599 */ 00600 00601 template<> struct ConvertToPyObject<double> 00602 { static PyObject* newPyObject(const double& x); }; 00603 00604 template<> struct ConvertToPyObject<float> 00605 { static PyObject* newPyObject(const float& x); }; 00606 00607 template<> struct ConvertToPyObject<char*> 00608 { static PyObject* newPyObject(const char* x); }; 00609 00610 template<size_t N> struct ConvertToPyObject<char[N]> 00611 { static PyObject* newPyObject(const char x[N]); }; 00612 00613 template<> struct ConvertToPyObject<string> 00614 { static PyObject* newPyObject(const string& x); }; 00615 00616 template<> struct ConvertToPyObject<PPath> 00617 { static PyObject* newPyObject(const PPath& x); }; 00618 00620 template<> struct ConvertToPyObject<Vec> 00621 { static PyObject* newPyObject(const Vec&); }; 00622 00624 template<> struct ConvertToPyObject<Mat> 00625 { static PyObject* newPyObject(const Mat&); }; 00626 00632 template<> struct ConvertToPyObject<PP<VMatrix> > 00633 { static PyObject* newPyObject(const PP<VMatrix>& vm); }; 00634 00636 template<class T> struct ConvertToPyObject<PP<T> > 00637 { static PyObject* newPyObject(const PP<T>&); }; 00638 00640 template<class T> 00641 struct ConvertToPyObject<tuple<T> > 00642 { static PyObject* newPyObject(const tuple<T>&); }; 00643 template <class T, class U> 00644 struct ConvertToPyObject<tuple<T,U> > 00645 { static PyObject* newPyObject(const tuple<T, U>&); }; 00646 template <class T, class U, class V> 00647 struct ConvertToPyObject<tuple<T,U,V> > 00648 { static PyObject* newPyObject(const tuple<T, U, V>&); }; 00649 template <class T, class U, class V, class W> 00650 struct ConvertToPyObject<tuple<T,U,V,W> > 00651 { static PyObject* newPyObject(const tuple<T, U, V, W>&); }; 00652 template <class T, class U, class V, class W, class X> 00653 struct ConvertToPyObject<tuple<T,U,V,W,X> > 00654 { static PyObject* newPyObject(const tuple<T, U, V, W, X>&); }; 00655 template <class T, class U, class V, class W, class X, class Y> 00656 struct ConvertToPyObject<tuple<T,U,V,W,X,Y> > 00657 { static PyObject* newPyObject(const tuple<T, U, V, W, X, Y>&); }; 00658 template <class T, class U, class V, class W, class X, class Y, class Z> 00659 struct ConvertToPyObject<tuple<T,U,V,W,X,Y,Z> > 00660 { static PyObject* newPyObject(const tuple<T, U, V, W, X, Y, Z>&); }; 00661 00663 template <class T> struct ConvertToPyObject<Array<T> > 00664 { static PyObject* newPyObject(const Array<T>&); }; 00665 00667 template <class T> struct ConvertToPyObject<TVec<T> > 00668 { static PyObject* newPyObject(const TVec<T>&); }; 00669 00671 template <class T> struct ConvertToPyObject<TMat<T> > 00672 { static PyObject* newPyObject(const TMat<T>&); }; 00673 00675 template <class T> struct ConvertToPyObject<std::vector<T> > 00676 { static PyObject* newPyObject(const std::vector<T>&); }; 00677 00679 template <class T, class U> struct ConvertToPyObject<std::map<T,U> > 00680 { static PyObject* newPyObject(const std::map<T,U>&); }; 00681 00683 template <class T> struct ConvertToPyObject<std::set<T> > 00684 { static PyObject* newPyObject(const std::set<T>&); }; 00685 00687 template <class T, class U> struct ConvertToPyObject<std::pair<T,U> > 00688 { static PyObject* newPyObject(const std::pair<T,U>&); }; 00689 00695 template <class T> struct ConvertToPyObject<std::vector<T> const* > 00696 { static PyObject* newPyObject(const std::vector<T>*); }; 00697 00699 template <class T, class U> struct ConvertToPyObject<std::map<T,U> const* > 00700 { static PyObject* newPyObject(const std::map<T,U>*); }; 00701 00703 template <class T> struct ConvertToPyObject<std::set<T> const* > 00704 { static PyObject* newPyObject(const std::set<T>*); }; 00705 00708 template<> struct ConvertToPyObject<PythonObjectWrapper> 00709 { static PyObject* newPyObject(const PythonObjectWrapper& pow); }; 00710 00711 template<> struct ConvertToPyObject<CopiesMap> 00712 { static PyObject* newPyObject(const CopiesMap& copies); }; 00713 00714 template <> struct ConvertToPyObject<VarArray> 00715 { static PyObject* newPyObject(const VarArray&); }; 00716 00717 template <> struct ConvertToPyObject<RealRange> 00718 { static PyObject* newPyObject(const RealRange&); }; 00719 00720 template <> struct ConvertToPyObject<VMField> 00721 { static PyObject* newPyObject(const VMField&); }; 00722 00723 struct PLPyClass 00724 { 00725 // holds info about a PLearn class 00726 // injected into python 00727 PLPyClass(PyObject* pyclass_, 00728 PP<PObjectPool<PyMethodDef> >& methods_) 00729 :pyclass(pyclass_), 00730 methods(methods_), 00731 methods_help(0), 00732 nref(1) 00733 {} 00734 PyObject* pyclass; 00735 PP<PObjectPool<PyMethodDef> > methods; 00736 TVec<string> methods_help; 00737 int nref; 00738 }; 00739 00740 //##### PythonGlobalInterpreterLock ######################################### 00741 00772 class PythonGlobalInterpreterLock 00773 { 00774 public: 00775 PythonGlobalInterpreterLock() 00776 : m_gilstate(PyGILState_Ensure()) 00777 { } 00778 00779 ~PythonGlobalInterpreterLock() 00780 { 00781 PyGILState_Release(m_gilstate); 00782 } 00783 00784 PyGILState_STATE m_gilstate; 00785 }; 00786 00787 00788 //##### PythonObjectWrapper ################################################# 00789 00809 class PythonObjectWrapper 00810 { 00811 public: 00818 enum OwnershipMode { 00819 control_ownership, 00820 transfer_ownership 00821 }; 00822 00823 static bool VMatAsPtr;//Object* or numpy array? 00824 00825 public: 00826 //##### Construction and Utility ######################################## 00827 00828 // Constructor from various C++ types. These create a new PyObject (owned 00829 // by default). 00830 00833 PythonObjectWrapper(OwnershipMode o = control_ownership, 00834 bool acquire_gil = true /* unused in this overload */); 00835 00837 PythonObjectWrapper(PyObject* pyobj, OwnershipMode o = control_ownership, 00838 bool acquire_gil = true /* unused in this overload */); 00839 00841 template <class T> 00842 explicit PythonObjectWrapper(const T& x, 00843 OwnershipMode o = control_ownership, 00844 bool acquire_gil = true) 00845 : m_ownership(o) 00846 { 00847 if (acquire_gil) { 00848 PythonGlobalInterpreterLock gil; 00849 m_object = ConvertToPyObject<T>::newPyObject(x); 00850 } 00851 else 00852 m_object = ConvertToPyObject<T>::newPyObject(x); 00853 } 00854 00856 PythonObjectWrapper(const PythonObjectWrapper& other); 00857 00860 ~PythonObjectWrapper(); 00861 00863 PythonObjectWrapper& operator=(const PythonObjectWrapper& rhs); 00864 00866 template<typename T> operator T() const { return as<T>(); } 00867 00869 void swap(PythonObjectWrapper& other); 00870 00872 PyObject* getPyObject() const 00873 { 00874 return m_object; 00875 } 00876 00878 bool isNull() const; 00879 00881 void printDebug() const; 00882 00883 00884 00885 //##### Conversion Back to C++ ########################################## 00886 00888 template <class T> 00889 T as() const 00890 { 00891 return ConvertFromPyObject<T>::convert(m_object, true); 00892 } 00893 00900 template <class T> 00901 T asNoTraceback() const 00902 { 00903 return ConvertFromPyObject<T>::convert(m_object, false); 00904 } 00905 00906 00907 //##### Trampoline for PLearn objects ##################################### 00908 00909 static PyObject* trampoline(PyObject* self, PyObject* args); 00910 00911 static PyObject* python_del(PyObject* self, PyObject* args); 00912 00913 static PyObject* newCPPObj(PyObject* self, PyObject* args); 00914 00915 static PyObject* refCPPObj(PyObject* self, PyObject* args); 00916 00917 static void gc_collect1(); 00918 00919 //##### Low-Level PyObject Creation ##################################### 00920 00925 static PyObject* newPyObject(); 00926 00931 static void initializePython(); 00932 00933 //for the unique unref injected method 00934 static bool m_unref_injected; 00935 static PyMethodDef m_unref_method_def; 00936 static PyMethodDef m_newCPPObj_method_def; 00937 static PyMethodDef m_refCPPObj_method_def; 00938 typedef map<const string, PLPyClass> pypl_classes_t; 00939 static pypl_classes_t m_pypl_classes; 00940 typedef map<const Object*, PyObject*> wrapped_objects_t; 00941 static wrapped_objects_t m_wrapped_objects; 00942 static wrapped_objects_t::iterator m_gc_next_object; 00943 00944 protected: 00945 OwnershipMode m_ownership; 00946 PyObject* m_object; 00947 00948 template<class T> friend class ConvertToPyObject; 00949 friend PStream& operator>>(PStream& in, PythonObjectWrapper& v); 00950 friend PStream& operator<<(PStream& out, const PythonObjectWrapper& v); 00951 }; 00952 00953 00954 // Specialization for General T*. Attempt to cast into Object*. If that works 00955 // we're all set; for specific pointer types (e.g. map<U,V>* and vector<T>*), 00956 // above, since they are more specialized they should kick in before this one. 00957 // This specialization is not grouped with other specializations because it 00958 // makes explicit use of the 'newPyObject' method in the PythonObjectWrapper 00959 // class, and gcc 4.0.2 does not allow this until that class is properly 00960 // declared. 00961 template <typename T> 00962 struct ConvertToPyObject<T*> 00963 { 00964 static PyObject* newPyObject(const T* x) 00965 { 00966 if(!x) // null ptr. becomes None 00967 return PythonObjectWrapper::newPyObject(); 00968 00969 if (const Object* objx = dynamic_cast<const Object*>(x)) 00970 return ConvertToPyObject<Object*>::newPyObject(objx); 00971 00972 PLERROR("Cannot convert type %s by value to python", 00973 TypeTraits<T*>::name().c_str()); 00974 return 0;//shut up compiler 00975 } 00976 }; 00977 00978 00979 //##### ConvertFromPyObject Implementations ################################# 00980 00981 template<class U, bool is_enum> 00982 struct StaticConvertEnumFromPyObject 00983 { 00984 static U convert(PyObject* x, bool print_traceback) 00985 { 00986 PLERROR("Cannot convert this object by value from python (type=%s).", 00987 TypeTraits<U>::name().c_str()); 00988 return U();//to silence compiler 00989 } 00990 }; 00991 00992 template<class U> 00993 struct StaticConvertEnumFromPyObject<U, true> 00994 { 00995 static U convert(PyObject* x, bool print_traceback) 00996 { 00997 return static_cast<U>( 00998 ConvertFromPyObject<int>::convert(x, print_traceback)); 00999 } 01000 }; 01001 01002 template <class T> 01003 T ConvertFromPyObject<T>::convert(PyObject* x, bool print_traceback) 01004 { 01005 return StaticConvertEnumFromPyObject<T, boost::is_enum<T>::value> 01006 ::convert(x, print_traceback); 01007 } 01008 01009 template <class T> 01010 PP<T> ConvertFromPyObject<PP<T> >::convert(PyObject* pyobj, 01011 bool print_traceback) 01012 { 01013 PLASSERT( pyobj ); 01014 if(pyobj == Py_None) 01015 return 0; 01016 01017 PPointable* o= 0; 01018 if(PyCObject_Check(pyobj)) 01019 o= ConvertFromPyObject<PPointable*>::convert(pyobj, print_traceback); 01020 else 01021 o= ConvertFromPyObject<Object*>::convert(pyobj, print_traceback); 01022 PP<T> p(dynamic_cast<T*>(o)); 01023 if(!p) 01024 PLPythonConversionError("ConvertFromPyObject<PP<T> >", pyobj, 01025 print_traceback); 01026 return p; 01027 } 01028 01029 /***** 01030 * convert numpy array to the right array type; return 0 if pyobj is not an array 01031 * pyobj is the python object to check/convert, numpy_type is an int representing a 01032 * numpy type, ndim is the number of dimensions that the array should have (1=vec, 2=mat, 0=any) 01033 */ 01034 PyObject* convertArrayCheck(PyObject* pyobj, int numpy_type, int ndim, bool print_traceback); 01035 01036 template <class T> 01037 Array<T> ConvertFromPyObject<Array<T> >::convert(PyObject* pyobj, 01038 bool print_traceback) 01039 { 01040 PLASSERT(pyobj); 01041 01042 // Here, we support both Python Tuples and Lists 01043 if(PyTuple_Check(pyobj)) { 01044 // Tuple case 01045 int size = PyTuple_GET_SIZE(pyobj); 01046 Array<T> v(size); 01047 for (int i=0 ; i<size ; ++i) { 01048 PyObject* elem_i = PyTuple_GET_ITEM(pyobj, i); 01049 v[i] = ConvertFromPyObject<T>::convert(elem_i, print_traceback); 01050 } 01051 return v; 01052 } 01053 else if (PyList_Check(pyobj)) { 01054 // List case 01055 int size = PyList_GET_SIZE(pyobj); 01056 Array<T> v(size); 01057 for (int i=0 ; i<size ; ++i) { 01058 PyObject* elem_i = PyList_GET_ITEM(pyobj, i); 01059 v[i] = ConvertFromPyObject<T>::convert(elem_i, print_traceback); 01060 } 01061 return v; 01062 } 01063 else if (PyObject* pyarr= convertArrayCheck(pyobj, numpyType<T>(), 1, print_traceback)) 01064 { 01065 int sz= PyArray_DIM(pyarr,0); 01066 Array<T> v(sz); 01067 v.copyFrom(static_cast<T*>(PyArray_DATA(pyarr)), sz); 01068 Py_XDECREF(pyarr); 01069 return v; 01070 } 01071 else 01072 PLPythonConversionError("ConvertFromPyObject<Array<T> >", pyobj, 01073 print_traceback); 01074 01075 return Array<T>(); // Shut up compiler 01076 } 01077 01078 template <class T> 01079 TVec<T> ConvertFromPyObject< TVec<T> >::convert(PyObject* pyobj, 01080 bool print_traceback) 01081 { 01082 PLASSERT( pyobj ); 01083 01084 // Here, we support both Python Tuples and Lists 01085 if (PyTuple_Check(pyobj)) { 01086 // Tuple case 01087 int size = PyTuple_GET_SIZE(pyobj); 01088 TVec<T> v(size); 01089 for (int i=0 ; i<size ; ++i) { 01090 PyObject* elem_i = PyTuple_GET_ITEM(pyobj, i); 01091 v[i] = ConvertFromPyObject<T>::convert(elem_i, print_traceback); 01092 } 01093 return v; 01094 } 01095 else if (PyList_Check(pyobj)) { 01096 // List case 01097 int size = PyList_GET_SIZE(pyobj); 01098 TVec<T> v(size); 01099 for (int i=0 ; i<size ; ++i) { 01100 PyObject* elem_i = PyList_GET_ITEM(pyobj, i); 01101 v[i] = ConvertFromPyObject<T>::convert(elem_i, print_traceback); 01102 } 01103 return v; 01104 } 01105 else if (PyObject* pyarr= convertArrayCheck(pyobj, numpyType<T>(), 1, print_traceback)) 01106 { 01107 int sz= PyArray_DIM(pyarr,0); 01108 TVec<T> v(sz); 01109 v.copyFrom(static_cast<T*>(PyArray_DATA(pyarr)), sz); 01110 Py_XDECREF(pyarr); 01111 return v; 01112 } 01113 else 01114 PLPythonConversionError("ConvertFromPyObject< TVec<T> >", pyobj, 01115 print_traceback); 01116 01117 return TVec<T>(); // Shut up compiler 01118 } 01119 01120 template <class T> 01121 TMat<T> ConvertFromPyObject<TMat<T> >::convert(PyObject* pyobj, 01122 bool print_traceback) 01123 { 01124 PLASSERT( pyobj ); 01125 01126 // Here, we support both Python Tuples and Lists 01127 if (PyTuple_Check(pyobj)) { 01128 // Tuple case 01129 int len= PyTuple_GET_SIZE(pyobj); 01130 TMat<T> v; 01131 for(int i= 0; i < len; ++i) 01132 { 01133 PyObject* row_i= PyTuple_GET_ITEM(pyobj, i); 01134 TVec<T> r= ConvertFromPyObject<TVec<T> >::convert(row_i, 01135 print_traceback); 01136 if(i == 0) 01137 v.resize(0, r.size()); 01138 v.appendRow(r); 01139 } 01140 return v; 01141 } 01142 else if (PyList_Check(pyobj)) { 01143 // List case 01144 int len= PyList_GET_SIZE(pyobj); 01145 TMat<T> v; 01146 for(int i= 0; i < len; ++i) 01147 { 01148 PyObject* row_i= PyList_GET_ITEM(pyobj, i); 01149 TVec<T> r= ConvertFromPyObject<TVec<T> >::convert(row_i, 01150 print_traceback); 01151 if(i == 0) 01152 v.resize(0, r.size()); 01153 v.appendRow(r); 01154 } 01155 return v; 01156 } 01157 else if (PyObject* pyarr= convertArrayCheck(pyobj, numpyType<T>(), 2, print_traceback)) 01158 { 01159 TMat<T> m; 01160 m.resize(PyArray_DIM(pyarr,0), PyArray_DIM(pyarr,1)); 01161 m.toVec().copyFrom(static_cast<T*>(PyArray_DATA(pyarr)), 01162 PyArray_DIM(pyarr,0) * PyArray_DIM(pyarr,1)); 01163 Py_XDECREF(pyarr); 01164 return m; 01165 } 01166 else 01167 PLPythonConversionError("ConvertFromPyObject< TMat<T> >", pyobj, 01168 print_traceback); 01169 01170 return TMat<T>(); // Shut up compiler 01171 } 01172 01173 01174 template <class T> 01175 std::vector<T> ConvertFromPyObject< std::vector<T> >::convert(PyObject* pyobj, 01176 bool print_traceback) 01177 { 01178 PLASSERT( pyobj ); 01179 01180 // Simple but inefficient implementation: create temporary TVec and copy 01181 // into a vector 01182 TVec<T> v = ConvertFromPyObject< TVec<T> >::convert(pyobj, print_traceback); 01183 return std::vector<T>(v.begin(), v.end()); 01184 } 01185 01186 template <class T, class U> 01187 std::map<T,U> ConvertFromPyObject< std::map<T,U> >::convert(PyObject* pyobj, 01188 bool print_traceback) 01189 { 01190 PLASSERT( pyobj ); 01191 if (! PyDict_Check(pyobj)) 01192 PLPythonConversionError("ConvertFromPyObject< std::map<T,U> >", pyobj, 01193 print_traceback); 01194 01195 PyObject *key, *value; 01196 #if PL_PYTHON_VERSION>=250 01197 Py_ssize_t pos = 0; 01198 #else 01199 int pos = 0; 01200 #endif 01201 std::map<T,U> result; 01202 01203 while (PyDict_Next(pyobj, &pos, &key, &value)) { 01204 T the_key = ConvertFromPyObject<T>::convert(key, print_traceback); 01205 U the_val = ConvertFromPyObject<U>::convert(value, print_traceback); 01206 result.insert(make_pair(the_key,the_val)); 01207 } 01208 return result; 01209 } 01210 01211 template <class T> 01212 std::set<T> ConvertFromPyObject<std::set<T> >::convert(PyObject* pyobj, 01213 bool print_traceback) 01214 { 01215 PLASSERT( pyobj ); 01216 PyObject* env= PyDict_New(); 01217 if(0 != PyDict_SetItemString(env, "__builtins__", PyEval_GetBuiltins())) 01218 PLERROR("in ConvertFromPyObject<std::set<T> >::convert : " 01219 "cannot insert builtins in env."); 01220 if(0 != PyDict_SetItemString(env, "the_set", pyobj)) 01221 PLERROR("in ConvertFromPyObject<std::set<T> >::convert : " 01222 "cannot insert the_set in env."); 01223 PyObject* res= PyRun_String("\nresult= list(the_set)\n", 01224 Py_file_input, env, env); 01225 if(!res) 01226 { 01227 Py_DECREF(env); 01228 if(PyErr_Occurred()) PyErr_Print(); 01229 PLERROR("in ConvertFromPyObject<std::set<T> >::convert : " 01230 "cannot convert to a set."); 01231 } 01232 Py_DECREF(res); 01233 TVec<PythonObjectWrapper> listobj= 01234 PythonObjectWrapper(env).as<std::map<string, PythonObjectWrapper> >()["result"]; 01235 Py_DECREF(env); 01236 std::set<T> the_set; 01237 for(TVec<PythonObjectWrapper>::iterator it= listobj.begin(); 01238 it != listobj.end(); ++it) 01239 the_set.insert(*it); 01240 return the_set; 01241 } 01242 01243 template <class T, class U> 01244 std::pair<T,U> ConvertFromPyObject< std::pair<T,U> >::convert(PyObject* pyobj, 01245 bool print_traceback) 01246 { 01247 PLASSERT( pyobj ); 01248 // Here, we support both Python Tuples and Lists 01249 if (! PyTuple_Check(pyobj) && PyTuple_GET_SIZE(pyobj) != 2) 01250 PLPythonConversionError("ConvertFromPyObject< std::pair<T,U> >", pyobj, 01251 print_traceback); 01252 01253 std::pair<T,U> p; 01254 01255 PyObject* first = PyTuple_GET_ITEM(pyobj, 0); 01256 p.first = ConvertFromPyObject<T>::convert(first, print_traceback); 01257 01258 PyObject* second = PyTuple_GET_ITEM(pyobj, 1); 01259 p.second = ConvertFromPyObject<U>::convert(second, print_traceback); 01260 01261 return p; 01262 } 01263 01264 //##### newPyObject Implementations ######################################### 01265 template<typename T, bool is_enum> 01266 struct StaticConvertEnumToPyObject 01267 { 01268 static PyObject* newPyObject(const T& x) 01269 { 01270 PLERROR("Cannot convert type %s by value to python.", 01271 TypeTraits<T>::name().c_str()); 01272 return 0;//shut up compiler 01273 } 01274 }; 01275 01276 template<typename T> 01277 struct StaticConvertEnumToPyObject<T, true> 01278 { 01279 static PyObject* newPyObject(const T& x) 01280 { 01281 return ConvertToPyObject<int>::newPyObject(x); 01282 } 01283 }; 01284 01285 template<typename T> 01286 PyObject* ConvertToPyObject<T>::newPyObject(const T& x) 01287 { 01288 return StaticConvertEnumToPyObject<T, boost::is_enum<T>::value> 01289 ::newPyObject(x); 01290 } 01291 01292 01293 template<size_t N> 01294 PyObject* ConvertToPyObject<char[N]>::newPyObject(const char x[N]) 01295 { 01296 return ConvertToPyObject<char*>::newPyObject(x); 01297 } 01298 01299 01300 template <class T> 01301 PyObject* ConvertToPyObject<PP<T> >::newPyObject(const PP<T>& data) 01302 { 01303 if(data == 0) 01304 return PythonObjectWrapper::newPyObject(); 01305 Object* o= dynamic_cast<Object*>(static_cast<T*>(data)); 01306 if(o) 01307 return ConvertToPyObject<Object*>::newPyObject(o); 01308 return ConvertToPyObject<T*>::newPyObject(static_cast<T*>(data)); 01309 } 01310 01311 template <class T> 01312 PyObject* ConvertToPyObject<Array<T> >::newPyObject(const Array<T>& data) 01313 { 01314 PyObject* newlist = PyList_New(data.size()); 01315 for (int i=0, n=data.size() ; i<n ; ++i) { 01316 // Since PyList_SET_ITEM steals the reference to the item being set, 01317 // one does not need to Py_XDECREF the inserted string as was required 01318 // for the PyArrayObject code above... 01319 PyList_SET_ITEM(newlist, i, ConvertToPyObject<T>::newPyObject(data[i])); 01320 } 01321 return newlist; 01322 } 01323 01324 template <class T> 01325 PyObject* ConvertToPyObject<TVec<T> >::newPyObject(const TVec<T>& data) 01326 { 01327 PyObject* newlist = PyList_New(data.size()); 01328 for (int i=0, n=data.size() ; i<n ; ++i) { 01329 // Since PyList_SET_ITEM steals the reference to the item being set, 01330 // one does not need to Py_XDECREF the inserted string as was required 01331 // for the PyArrayObject code above... 01332 PyList_SET_ITEM(newlist, i, ConvertToPyObject<T>::newPyObject(data[i])); 01333 } 01334 return newlist; 01335 } 01336 01337 template <class T> 01338 PyObject* ConvertToPyObject<TMat<T> >::newPyObject(const TMat<T>& data) 01339 { 01340 PyObject* newlist = PyList_New(data.length()); 01341 for (int i=0, n=data.length() ; i<n ; ++i) 01342 { 01343 // Since PyList_SET_ITEM steals the reference to the item being set, 01344 // one does not need to Py_XDECREF the inserted string as was required 01345 // for the PyArrayObject code above... 01346 PyList_SET_ITEM(newlist, i, 01347 ConvertToPyObject<TVec<T> >::newPyObject(data(i))); 01348 } 01349 return newlist; 01350 } 01351 01352 template <class T> 01353 PyObject* ConvertToPyObject<std::vector<T> >::newPyObject(const std::vector<T>& data) 01354 { 01355 PyObject* newlist = PyList_New(data.size()); 01356 for (int i=0, n=data.size() ; i<n ; ++i) { 01357 // Since PyList_SET_ITEM steals the reference to the item being set, 01358 // one does not need to Py_XDECREF the inserted string as was required 01359 // for the PyArrayObject code above... 01360 PyList_SET_ITEM(newlist, i, ConvertToPyObject<T>::newPyObject(data[i])); 01361 } 01362 return newlist; 01363 } 01364 01365 template <class T, class U> 01366 PyObject* ConvertToPyObject<std::map<T,U> >::newPyObject(const std::map<T,U>& data) 01367 { 01368 // From the Python C API Documentation section 1.10.2: (Note that 01369 // PyDict_SetItem() and friends don't take over ownership -- they are 01370 // ``normal.'') 01371 PyObject* newdict = PyDict_New(); 01372 for (typename std::map<T,U>::const_iterator it = data.begin(), end = data.end() ; 01373 it != end ; ++it) 01374 { 01375 PyObject* new_key = ConvertToPyObject<T>::newPyObject(it->first); 01376 PyObject* new_val = ConvertToPyObject<U>::newPyObject(it->second); 01377 int non_success = PyDict_SetItem(newdict, new_key, new_val); 01378 Py_XDECREF(new_key); 01379 Py_XDECREF(new_val); 01380 01381 if (non_success) 01382 PLERROR("PythonObjectWrapper::newPyObject: cannot insert element '%s':'%s' " 01383 "into Python dict", 01384 tostring(it->first).c_str(), 01385 tostring(it->second).c_str()); 01386 } 01387 01388 return newdict; 01389 } 01390 01391 template <class T> 01392 PyObject* ConvertToPyObject<std::set<T> >::newPyObject(const std::set<T>& data) 01393 { 01394 TVec<T> as_list(data.size()); 01395 int i= 0; 01396 for(typename std::set<T>::const_iterator it= data.begin(); 01397 it != data.end(); ++it, ++i) 01398 as_list[i]= *it; 01399 PyObject* pylist= ConvertToPyObject<TVec<T> >::newPyObject(as_list); 01400 PyObject* env= PyDict_New(); 01401 if(0 != PyDict_SetItemString(env, "__builtins__", PyEval_GetBuiltins())) 01402 PLERROR("in ConvertToPyObject<std::set<T> >::newPyObject : " 01403 "cannot insert builtins in env."); 01404 if(0 != PyDict_SetItemString(env, "the_list", pylist)) 01405 PLERROR("in ConvertToPyObject<std::set<T> >::newPyObject : " 01406 "cannot insert the_list in env."); 01407 string code= ""; 01408 #if PL_PYTHON_VERSION <= 230 01409 code+= "\nfrom sets import Set as set\n"; 01410 #endif // PL_PYTHON_VERSION <= 230 01411 code+= "\nresult= set(the_list)\n"; 01412 PyObject* res= PyRun_String(const_cast<const char*>(code.c_str()), 01413 Py_file_input, env, env); 01414 Py_DECREF(pylist); 01415 if(!res) 01416 { 01417 Py_DECREF(env); 01418 if(PyErr_Occurred()) PyErr_Print(); 01419 PLERROR("in ConvertToPyObject<std::set<T> >::newPyObject : " 01420 "cannot convert to a set."); 01421 } 01422 Py_DECREF(res); 01423 PyObject* setobj= 01424 PythonObjectWrapper(env).as<map<string, PyObject*> >()["result"]; 01425 Py_INCREF(setobj); 01426 Py_DECREF(env); 01427 return setobj; 01428 } 01429 01430 template <class T, class U> 01431 PyObject* ConvertToPyObject<std::pair<T,U> >::newPyObject(const std::pair<T,U>& data) 01432 { 01433 // According to Python Doc, since PyTuple_SET_ITEM steals the reference to 01434 // the item being set, one does not need to Py_XDECREF the inserted object. 01435 PyObject* newtuple = PyTuple_New(2); 01436 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(data.first)); 01437 PyTuple_SET_ITEM(newtuple, 1, ConvertToPyObject<U>::newPyObject(data.second)); 01438 return newtuple; 01439 } 01440 01441 template <class T> 01442 PyObject* ConvertToPyObject<tuple<T> >::newPyObject(const tuple<T>& data) 01443 { 01444 PyObject* newtuple= PyTuple_New(1); 01445 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(get<0>(data))); 01446 return newtuple; 01447 } 01448 01449 template <class T, class U> 01450 PyObject* ConvertToPyObject<tuple<T,U> >::newPyObject(const tuple<T, U>& data) 01451 { 01452 PyObject* newtuple= PyTuple_New(2); 01453 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(get<0>(data))); 01454 PyTuple_SET_ITEM(newtuple, 1, ConvertToPyObject<U>::newPyObject(get<1>(data))); 01455 return newtuple; 01456 } 01457 01458 template <class T, class U, class V> 01459 PyObject* ConvertToPyObject<tuple<T,U,V> >::newPyObject(const tuple<T, U, V>& data) 01460 { 01461 PyObject* newtuple= PyTuple_New(3); 01462 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(get<0>(data))); 01463 PyTuple_SET_ITEM(newtuple, 1, ConvertToPyObject<U>::newPyObject(get<1>(data))); 01464 PyTuple_SET_ITEM(newtuple, 2, ConvertToPyObject<V>::newPyObject(get<2>(data))); 01465 return newtuple; 01466 } 01467 01468 template <class T, class U, class V, class W> 01469 PyObject* ConvertToPyObject<tuple<T,U,V,W> >::newPyObject(const tuple<T, U, V, W>& data) 01470 { 01471 PyObject* newtuple= PyTuple_New(4); 01472 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(get<0>(data))); 01473 PyTuple_SET_ITEM(newtuple, 1, ConvertToPyObject<U>::newPyObject(get<1>(data))); 01474 PyTuple_SET_ITEM(newtuple, 2, ConvertToPyObject<V>::newPyObject(get<2>(data))); 01475 PyTuple_SET_ITEM(newtuple, 3, ConvertToPyObject<W>::newPyObject(get<3>(data))); 01476 return newtuple; 01477 } 01478 01479 template <class T, class U, class V, class W, class X> 01480 PyObject* ConvertToPyObject<tuple<T,U,V,W,X> >::newPyObject(const tuple<T, U, V, W, X>& data) 01481 { 01482 PyObject* newtuple= PyTuple_New(5); 01483 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(get<0>(data))); 01484 PyTuple_SET_ITEM(newtuple, 1, ConvertToPyObject<U>::newPyObject(get<1>(data))); 01485 PyTuple_SET_ITEM(newtuple, 2, ConvertToPyObject<V>::newPyObject(get<2>(data))); 01486 PyTuple_SET_ITEM(newtuple, 3, ConvertToPyObject<W>::newPyObject(get<3>(data))); 01487 PyTuple_SET_ITEM(newtuple, 4, ConvertToPyObject<X>::newPyObject(get<4>(data))); 01488 return newtuple; 01489 } 01490 01491 template <class T, class U, class V, class W, class X, class Y> 01492 PyObject* ConvertToPyObject<tuple<T,U,V,W,X,Y> >::newPyObject(const tuple<T, U, V, W, X, Y>& data) 01493 { 01494 PyObject* newtuple= PyTuple_New(6); 01495 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(get<0>(data))); 01496 PyTuple_SET_ITEM(newtuple, 1, ConvertToPyObject<U>::newPyObject(get<1>(data))); 01497 PyTuple_SET_ITEM(newtuple, 2, ConvertToPyObject<V>::newPyObject(get<2>(data))); 01498 PyTuple_SET_ITEM(newtuple, 3, ConvertToPyObject<W>::newPyObject(get<3>(data))); 01499 PyTuple_SET_ITEM(newtuple, 4, ConvertToPyObject<X>::newPyObject(get<4>(data))); 01500 PyTuple_SET_ITEM(newtuple, 5, ConvertToPyObject<Y>::newPyObject(get<5>(data))); 01501 return newtuple; 01502 } 01503 01504 template <class T, class U, class V, class W, class X, class Y, class Z> 01505 PyObject* ConvertToPyObject<tuple<T,U,V,W,X,Y,Z> >::newPyObject(const tuple<T, U, V, W, X, Y, Z>& data) 01506 { 01507 PyObject* newtuple= PyTuple_New(7); 01508 PyTuple_SET_ITEM(newtuple, 0, ConvertToPyObject<T>::newPyObject(get<0>(data))); 01509 PyTuple_SET_ITEM(newtuple, 1, ConvertToPyObject<U>::newPyObject(get<1>(data))); 01510 PyTuple_SET_ITEM(newtuple, 2, ConvertToPyObject<V>::newPyObject(get<2>(data))); 01511 PyTuple_SET_ITEM(newtuple, 3, ConvertToPyObject<W>::newPyObject(get<3>(data))); 01512 PyTuple_SET_ITEM(newtuple, 4, ConvertToPyObject<X>::newPyObject(get<4>(data))); 01513 PyTuple_SET_ITEM(newtuple, 5, ConvertToPyObject<Y>::newPyObject(get<5>(data))); 01514 PyTuple_SET_ITEM(newtuple, 6, ConvertToPyObject<Z>::newPyObject(get<6>(data))); 01515 return newtuple; 01516 } 01517 01518 template <class T> 01519 PyObject* ConvertToPyObject<std::vector<T> const* >::newPyObject(const std::vector<T>* data) 01520 { 01521 if (data) 01522 return ConvertToPyObject<std::vector<T> >::newPyObject(*data); 01523 else 01524 return PythonObjectWrapper::newPyObject(); 01525 } 01526 01527 template <class T, class U> 01528 PyObject* ConvertToPyObject<std::map<T,U> const* >::newPyObject(const std::map<T,U>* data) 01529 { 01530 if (data) 01531 return ConvertToPyObject<std::map<T,U> >::newPyObject(*data); 01532 else 01533 return PythonObjectWrapper::newPyObject(); 01534 } 01535 01536 template <class T> 01537 PyObject* ConvertToPyObject<std::set<T> const* >::newPyObject(const std::set<T>* data) 01538 { 01539 if(data) 01540 return ConvertToPyObject<std::set<T> >::newPyObject(*data); 01541 else 01542 return PythonObjectWrapper::newPyObject(); 01543 } 01544 01545 01546 PStream& operator>>(PStream& in, PythonObjectWrapper& v); 01547 PStream& operator<<(PStream& out, const PythonObjectWrapper& v); 01548 PStream& operator>>(PStream& in, PyObject* v); 01549 PStream& operator<<(PStream& out, const PyObject* v); 01550 DECLARE_TYPE_TRAITS(PythonObjectWrapper); 01551 01553 void printWrappedObjects(); 01554 void ramassePoubelles(); 01555 01556 bool getVMatAsPtr(); 01557 bool setVMatAsPtr(bool vmat_as_ptr= true); 01558 01559 } // end of namespace PLearn 01560 01561 #endif 01562 01563 01564 /* 01565 Local Variables: 01566 mode:c++ 01567 c-basic-offset:4 01568 c-file-style:"stroustrup" 01569 c-file-offsets:((innamespace . 0)(inline-open . 0)) 01570 indent-tabs-mode:nil 01571 fill-column:79 01572 End: 01573 */ 01574 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :