PLearn 0.1
PythonObjectWrapper.h
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines