/* * PythonScripting.hpp * * Created on: Apr 13, 2012 * Author: heber */ #ifndef PYTHONSCRIPTING_HPP_ #define PYTHONSCRIPTING_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include //!> define all present actions #include "GlobalListOfActions.hpp" //!> python wrapping for all of these actions #include "AllActionPython.hpp" namespace MoleCuilder { namespace PythonTypes { inline void IndexError(){ PyErr_SetString(PyExc_IndexError, "Index out of range"); boost::python::throw_error_already_set(); } template struct vec_item{ typedef typename T::value_type V; static V& get(T& x, int i){ static V nothing; if(i < 0) i += x.size(); if(i >= 0 && i < int(x.size())) return x[i]; IndexError(); return nothing; } static void set(T& x, int i, V const& v){ if(i < 0) i += x.size(); if(i >= 0 && i < int(x.size())) x[i] = v; else IndexError(); } static void del(T& x, int i){ if(i < 0) i += x.size(); if(i >= 0 && i < int(x.size())) x.erase(x.begin() + i); else IndexError(); } static void add(T& x, V const& v){ x.push_back(v); } }; } /* namespace PythonTypes */ } /* namespace MoleCuilder */ BOOST_PYTHON_MODULE(pyMoleCuilder) { // set the docstring of the current module scope boost::python::scope().attr("__doc__") = "pyMolecuilder are the python bindings to all Actions of the program suite MoleCuilder.\n\nMoleCuilder is a program to build molecular (dynamics) worlds, allowing you indefinite manipulation, control and analysis over the atoms and molecules within a simulation domain."; // STL Vectors: // doubleVec boost::python::class_< std::vector< double > >("PythonType_doubleVec") .def("__len__", &std::vector< double >::size) .def("clear", &std::vector< double >::clear) .def("append", &MoleCuilder::PythonTypes::vec_item< std::vector< double > >::add, boost::python::with_custodian_and_ward<1, 2>()) // let container keep value .def("__getitem__", &MoleCuilder::PythonTypes::vec_item< std::vector< double > >::get, boost::python::return_value_policy()) .def("__setitem__", &MoleCuilder::PythonTypes::vec_item< std::vector< double > >::set, boost::python::with_custodian_and_ward<1,2>()) // to let container keep value .def("__delitem__", &MoleCuilder::PythonTypes::vec_item< std::vector< double > >::del) .def("__iter__", boost::python::iterator< std::vector< double > >()) ; #define export_print(z,n,list) \ BOOST_PP_CAT(export_, BOOST_PP_SEQ_ELEM(n, list))(); #define BOOST_PP_LOCAL_MACRO(n) export_print(~, n, GLOBALLISTOFACTIONS) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(GLOBALLISTOFACTIONS))) #include BOOST_PP_LOCAL_ITERATE() #undef instance_print } bool executePythonScript(const std::string &pythonfilename_string) { boost::filesystem::path pythonfilename(pythonfilename_string); if (exists(pythonfilename)) { // parse in and execute the local and global config.py try { PyImport_AppendInittab( "pyMoleCuilder", &initpyMoleCuilder ); Py_Initialize(); boost::python::object main_module(( boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("__main__"))))); boost::python::object main_namespace = main_module.attr("__dict__"); boost::python::object molecuilder_module( (boost::python::handle<>(PyImport_ImportModule("pyMoleCuilder"))) ); main_namespace["pyMoleCuilder"] = molecuilder_module; // parse file into a string std::ifstream pythonfile(pythonfilename.string().c_str()); std::string pythonscript( std::istreambuf_iterator(pythonfile), (std::istreambuf_iterator()) ); std::string enveloped_script("print \"BEGIN of "+pythonfilename_string+":\"\n"); enveloped_script += pythonscript; enveloped_script += std::string("print \"END of "+pythonfilename_string+":\"\n"); boost::python::handle<> ignored(( PyRun_String( enveloped_script.c_str(), Py_file_input, main_namespace.ptr(), main_namespace.ptr() ) )); } catch( boost::python::error_already_set ) { PyErr_Print(); } } } #endif /* PYTHONSCRIPTING_HPP_ */