PLearn 0.1
PythonCodeSnippet.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PythonCodeSnippet.h
00004 //
00005 // Copyright (C) 2005 Nicolas Chapados
00006 //
00007 // Redistribution and use in source and binary forms, with or without
00008 // modification, are permitted provided that the following conditions are met:
00009 //
00010 //  1. Redistributions of source code must retain the above copyright
00011 //     notice, this list of conditions and the following disclaimer.
00012 //
00013 //  2. Redistributions in binary form must reproduce the above copyright
00014 //     notice, this list of conditions and the following disclaimer in the
00015 //     documentation and/or other materials provided with the distribution.
00016 //
00017 //  3. The name of the authors may not be used to endorse or promote
00018 //     products derived from this software without specific prior written
00019 //     permission.
00020 //
00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031 //
00032 // This file is part of the PLearn library. For more information on the PLearn
00033 // library, go to the PLearn Web site at www.plearn.org
00034 
00035 /* *******************************************************
00036  * $Id: PythonCodeSnippet.h 2797 2005-08-25 14:06:26Z chapados $
00037  ******************************************************* */
00038 
00039 // Authors: Nicolas Chapados
00040 
00043 #ifndef PythonCodeSnippet_INC
00044 #define PythonCodeSnippet_INC
00045 
00046 // Python stuff must be included first
00047 #include <plearn/python/PythonGlobalInterpreterLock.h>
00048 #include <plearn/python/PythonObjectWrapper.h>
00049 
00050 // Boost stuff
00051 #include <boost/function.hpp>
00052 #include <boost/bind.hpp>
00053 
00054 // PLearn stuff
00055 #include <plearn/base/Object.h>
00056 #include <plearn/base/plexceptions.h>
00057 #include <plearn/base/PMemPool.h>
00058 
00059 
00060 namespace PLearn {
00061 using namespace std;
00062 
00070 class PythonException : public PLearnError
00071 {
00072     typedef PLearnError inherited;
00073 
00074 public:
00075     PythonException(const string& message)
00076         : inherited(message)
00077     { }
00078 };
00079 
00080 
00110 class PythonCodeSnippet : public Object
00111 {
00112     typedef Object inherited;
00113 
00114 public:
00119     typedef boost::function<PythonObjectWrapper (
00120         const TVec<PythonObjectWrapper>& args)> StandaloneFunction;
00121 
00123     static const char* InjectSetupSnippet;
00124 
00126     static const char* SetCurrentSnippetVar;
00127     static const char* ResetCurrentSnippetVar;
00128 
00129 public:
00141     string m_code;
00142 
00148     bool m_remap_python_exceptions;
00149 
00151     map<string, string> m_instance_params;
00152 
00154     PythonObjectWrapper m_instance;
00155 
00156 public:
00160     PythonCodeSnippet(const string& code = "",
00161                       bool remap_python_exceptions = false);
00162 
00163     PythonCodeSnippet(const PythonObjectWrapper& instance,
00164                       bool remap_python_exceptions = false);
00165 
00167 
00168 
00169     //#####  Global Environment Interface  ####################################
00170 
00173     PythonObjectWrapper getGlobalObject(const string& object_name) const;
00174 
00176     void setGlobalObject(const string& object_name,
00177                          const PythonObjectWrapper& pow);
00178     template<typename T>
00179     void setGlobalObject(const string& object_name,
00180                          const T& o)
00181     {
00182         setGlobalObject(object_name, PythonObjectWrapper(o));
00183     }
00184 
00185 
00186 
00187     //#####  Function Call Interface  #########################################
00188 
00190     bool isInvokable(const char* function_name) const;
00191 
00193     PythonObjectWrapper invoke(const char* function_name) const;
00194 
00198     PythonObjectWrapper invoke(const char* function_name,
00199                                const TVec<PythonObjectWrapper>& args) const;
00200 
00202     template <class T>
00203     PythonObjectWrapper invoke(const char* function_name,
00204                                const T& arg1) const;
00205 
00207     template <class T, class U>
00208     PythonObjectWrapper invoke(const char* function_name,
00209                                const T& arg1,
00210                                const U& arg2) const;
00211 
00213     template <class T, class U, class V>
00214     PythonObjectWrapper invoke(const char* function_name,
00215                                const T& arg1,
00216                                const U& arg2,
00217                                const V& arg3) const;
00218 
00220     template <class T, class U, class V, class W>
00221     PythonObjectWrapper invoke(const char* function_name,
00222                                const T& arg1,
00223                                const U& arg2,
00224                                const V& arg3,
00225                                const W& arg4) const;
00226 
00228     template <class T, class U, class V, class W, class X>
00229     PythonObjectWrapper invoke(const char* function_name,
00230                                const T& arg1,
00231                                const U& arg2,
00232                                const V& arg3,
00233                                const W& arg4,
00234                                const X& arg5) const;
00235 
00237     template <class T, class U, class V, class W, class X, class Y>
00238     PythonObjectWrapper invoke(const char* function_name,
00239                                const T& arg1,
00240                                const U& arg2,
00241                                const V& arg3,
00242                                const W& arg4,
00243                                const X& arg5,
00244                                const Y& arg6) const;
00245 
00247     template <class T, class U, class V, class W, class X, class Y, class Z>
00248     PythonObjectWrapper invoke(const char* function_name,
00249                                const T& arg1,
00250                                const U& arg2,
00251                                const V& arg3,
00252                                const W& arg4,
00253                                const X& arg5,
00254                                const Y& arg6,
00255                                const Z& arg7) const;
00256 
00257 
00258     //#####  Function Injection Interface  ####################################
00259 
00281     void inject(const char* python_name, StandaloneFunction function_ptr);
00282 
00287     template <class T>
00288     void inject(const char* python_name, const T* object,
00289                 PythonObjectWrapper (T::*)(const TVec<PythonObjectWrapper>&) const);
00290 
00295     template <class T>
00296     void inject(const char* python_name, T* object,
00297                 PythonObjectWrapper (T::*)(const TVec<PythonObjectWrapper>&));
00298 
00299 
00304     void dumpPythonEnvironment();
00305 
00306 
00307     //#####  PLearn::Object Standard Functions  ###############################
00308 
00309     // Declares other standard object methods
00310     PLEARN_DECLARE_OBJECT(PythonCodeSnippet);
00311 
00312     // simply calls inherited::build() then build_()
00313     virtual void build();
00314 
00316     virtual void makeDeepCopyFromShallowCopy(CopiesMap& copies);
00317 
00318     virtual void run();
00319 
00320 protected:
00322     static void declareOptions(OptionList& ol);
00323 
00326     PythonObjectWrapper compileGlobalCode(const string& code); //const;
00327 
00328     void setCurrentSnippet(const void* handle) const;
00329     void resetCurrentSnippet() const;
00330 
00334     void handlePythonErrors(const string& extramsg= "") const;
00335 
00337     static PyObject* pythonTrampoline(PyObject* self, PyObject* args);
00338 
00342     void injectInternal(const char* python_name, StandaloneFunction* function_ptr);
00343 
00344 protected:
00346     void* m_handle;
00347 
00348 public:
00350     PythonObjectWrapper m_compiled_code;
00351 
00352 protected:
00354     PObjectPool<StandaloneFunction> m_injected_functions;
00355 
00357     PObjectPool<PyMethodDef> m_python_methods;
00358 
00359 private:
00362     void build_();
00363 };
00364 
00365 // Declares a few other classes and functions related to this class
00366 DECLARE_OBJECT_PTR(PythonCodeSnippet);
00367 
00368 
00369 //#####  Implementation of call  ##############################################
00370 
00371 template <class T>
00372 PythonObjectWrapper
00373 PythonCodeSnippet::invoke(const char* function_name,
00374                           const T& arg1) const
00375 {
00376     TVec<PythonObjectWrapper> args(1);
00377     args[0]= PythonObjectWrapper(arg1);
00378     return invoke(function_name, args);
00379 }
00380 
00381 
00382 template <class T, class U>
00383 PythonObjectWrapper
00384 PythonCodeSnippet::invoke(const char* function_name,
00385                           const T& arg1,
00386                           const U& arg2) const
00387 {
00388     TVec<PythonObjectWrapper> args(2);
00389     args[0]= PythonObjectWrapper(arg1);
00390     args[1]= PythonObjectWrapper(arg2);
00391     return invoke(function_name, args);
00392 }
00393 
00394 
00395 template <class T, class U, class V>
00396 PythonObjectWrapper
00397 PythonCodeSnippet::invoke(const char* function_name,
00398                           const T& arg1,
00399                           const U& arg2,
00400                           const V& arg3) const
00401 {
00402     TVec<PythonObjectWrapper> args(3);
00403     args[0]= PythonObjectWrapper(arg1);
00404     args[1]= PythonObjectWrapper(arg2);
00405     args[2]= PythonObjectWrapper(arg3);
00406     return invoke(function_name, args);
00407 }
00408 
00409 
00410 template <class T, class U, class V, class W>
00411 PythonObjectWrapper
00412 PythonCodeSnippet::invoke(const char* function_name,
00413                           const T& arg1,
00414                           const U& arg2,
00415                           const V& arg3,
00416                           const W& arg4) const
00417 {
00418     TVec<PythonObjectWrapper> args(4);
00419     args[0]= PythonObjectWrapper(arg1);
00420     args[1]= PythonObjectWrapper(arg2);
00421     args[2]= PythonObjectWrapper(arg3);
00422     args[3]= PythonObjectWrapper(arg4);
00423     return invoke(function_name, args);
00424 }
00425 
00426 template <class T, class U, class V, class W, class X>
00427 PythonObjectWrapper
00428 PythonCodeSnippet::invoke(const char* function_name,
00429                           const T& arg1,
00430                           const U& arg2,
00431                           const V& arg3,
00432                           const W& arg4,
00433                           const X& arg5) const
00434 {
00435     TVec<PythonObjectWrapper> args(5);
00436     args[0]= PythonObjectWrapper(arg1);
00437     args[1]= PythonObjectWrapper(arg2);
00438     args[2]= PythonObjectWrapper(arg3);
00439     args[3]= PythonObjectWrapper(arg4);
00440     args[4]= PythonObjectWrapper(arg5);
00441     return invoke(function_name, args);
00442 }
00443 
00444 template <class T, class U, class V, class W, class X, class Y>
00445 PythonObjectWrapper
00446 PythonCodeSnippet::invoke(const char* function_name,
00447                           const T& arg1,
00448                           const U& arg2,
00449                           const V& arg3,
00450                           const W& arg4,
00451                           const X& arg5,
00452                           const Y& arg6) const
00453 {
00454     TVec<PythonObjectWrapper> args(6);
00455     args[0]= PythonObjectWrapper(arg1);
00456     args[1]= PythonObjectWrapper(arg2);
00457     args[2]= PythonObjectWrapper(arg3);
00458     args[3]= PythonObjectWrapper(arg4);
00459     args[4]= PythonObjectWrapper(arg5);
00460     args[5]= PythonObjectWrapper(arg6);
00461     return invoke(function_name, args);
00462 }
00463 
00464 
00465 template <class T, class U, class V, class W, class X, class Y, class Z>
00466 PythonObjectWrapper
00467 PythonCodeSnippet::invoke(const char* function_name,
00468                           const T& arg1,
00469                           const U& arg2,
00470                           const V& arg3,
00471                           const W& arg4,
00472                           const X& arg5,
00473                           const Y& arg6,
00474                           const Z& arg7) const
00475 {
00476     TVec<PythonObjectWrapper> args(7);
00477     args[0]= PythonObjectWrapper(arg1);
00478     args[1]= PythonObjectWrapper(arg2);
00479     args[2]= PythonObjectWrapper(arg3);
00480     args[3]= PythonObjectWrapper(arg4);
00481     args[4]= PythonObjectWrapper(arg5);
00482     args[5]= PythonObjectWrapper(arg6);
00483     args[6]= PythonObjectWrapper(arg7);
00484     return invoke(function_name, args);
00485 }
00486 
00487 
00488 //#####  Implementation of inject  ############################################
00489 
00490 template <class T>
00491 void PythonCodeSnippet::inject(
00492     const char* python_name, const T* object,
00493     PythonObjectWrapper (T::*member_function)(const TVec<PythonObjectWrapper>&) const)
00494 {
00495     StandaloneFunction func = boost::bind(member_function, object, _1);
00496     inject(python_name, func);
00497 }
00498 
00499 template <class T>
00500 void PythonCodeSnippet::inject(
00501     const char* python_name, T* object,
00502     PythonObjectWrapper (T::*member_function)(const TVec<PythonObjectWrapper>&))
00503 {
00504     StandaloneFunction func = boost::bind(member_function, object, _1);
00505     inject(python_name, func);
00506 }
00507 
00508 
00509 
00510 } // end of namespace PLearn
00511 
00512 #endif
00513 
00514 
00515 /*
00516   Local Variables:
00517   mode:c++
00518   c-basic-offset:4
00519   c-file-style:"stroustrup"
00520   c-file-offsets:((innamespace . 0)(inline-open . 0))
00521   indent-tabs-mode:nil
00522   fill-column:79
00523   End:
00524 */
00525 // 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