optimized ${QT_QTCORE_LIBRARY}
debug ${QT_QTCORE_LIBRARY_DEBUG}
)
- SET(STATIC_PYTHON_TARGETS "")
- SET(SHARED_PYTHON_TARGETS "")
-
+ GET_MUSSA_COMPILE_FLAGS(PY_CFLAGS)
+ GET_MUSSA_LINK_FLAGS(PY_LDFLAGS)
+
+ # configure static core python library
ADD_LIBRARY(mussa_py STATIC ${SOURCES})
- SET(${STATIC_PYTHON_TARGETS} "${${STATIC_PYTHON_TARGETS}} mussa_py")
+ SET_TARGET_PROPERTIES(mussa_py PROPERTIES
+ COMPILE_FLAGS "${PY_CFLAGS}"
+ LINK_FLAGS "${PY_LDFLAGS}")
+
+ # configure core (shared) python module
ADD_LIBRARY(mussa MODULE ${SOURCES})
- SET(${SHARED_PYTHON_TARGETS} "${${SHARED_PYTHON_TARGETS}} mussa")
+ SET_TARGET_PROPERTIES(mussa PROPERTIES
+ PREFIX ""
+ COMPILE_FLAGS "${PY_CFLAGS}"
+ LINK_FLAGS "${PY_LDFLAGS}")
TARGET_LINK_LIBRARIES(mussa
${MUSSA_LIBRARIES}
)
+ # configure static gui python library
ADD_LIBRARY(mussaqui_py STATIC ${QUI_SOURCES})
- SET(${STATIC_PYTHON_TARGETS} "${${STATIC_PYTHON_TARGETS}} mussaqui_py")
- # ADD_LIBRARY(mussaqui MODULE ${QUI_SOURCES})
- # SET(${SHARED_PYTHON_TARGETS} "${${SHARED_PYTHON_TARGETS}} mussaqui")
+ SET_TARGET_PROPERTIES(mussa_py PROPERTIES
+ COMPILE_FLAGS "${PY_CFLAGS}"
+ LINK_FLAGS "${PY_LDFLAGS}")
+
+ # configure gui (shared) python library
+ #ADD_LIBRARY(mussaqui MODULE ${QUI_SOURCES})
+ #SET_TARGET_PROPERTIES(mussaqui PROPERTIES
+ # PREFIX ""
+ # COMPILE_FLAGS "${PY_CFLAGS}"
+ # LINK_FLAGS "${PY_LDFLAGS}")
#TARGET_LINK_LIBRARIES(mussaqui
# mussa_qui
# ${MUSSA_LIBRARIES}
# debug ${QT_QTOPENGL_LIBRARY_DEBUG}
# )
- # don't put the "lib" prefix infront of our shared modules
- SET_TARGET_PROPERTIES(${SHARED_PYTHON_TARGETS}
- PROPERTIES
- PREFIX ""
- )
- GET_MUSSA_COMPILE_FLAGS(PY_CFLAGS)
- GET_MUSSA_LINK_FLAGS(PY_LDFLAGS)
SET_SOURCE_FILES_PROPERTIES(
${SOURCES}
${QUI_SOURCES}
#include <boost/algorithm/string/classification.hpp>
namespace alg = boost::algorithm;
+
MussaPython::MussaPython()
+{
+}
+
+void MussaPython::add_module(const std::string &name, python_module_init initfunc)
+{
+ python_modules.push_back( module_item(name, initfunc) );
+}
+
+void MussaPython::AppendInittab(const module_item &item)
+{
+ PyImport_AppendInittab(const_cast<char *>(item.first.c_str()), item.second);
+}
+
+void MussaPython::init_interpreter()
{
try {
- // add our mussa module to our environment
- PyImport_AppendInittab("mussa", &initmussa);
- PyImport_AppendInittab("mussaqui", &initmussaqui);
+ // add any compiled in modules to our environment
+ for_each(python_modules.begin(), python_modules.end(), AppendInittab);
// go ahead and finish initalizing python
Py_Initialize();
// get reference to the global namespace
py::object main_module(
(py::handle<>(py::borrowed(PyImport_AddModule("__main__"))))
);
+ // setting the main_namespace must come before any calls to run or eval
main_namespace = main_module.attr("__dict__");
- // FIXME: this really should be a configuration file?
- run("import __main__\n"
- "import mussa\n"
- "import mussaqui");
+ run("import __main__\n");
+ // import modules that were added to us into the interpreter
+ for(module_list::const_iterator item = python_modules.begin();
+ item != python_modules.end();
+ ++item)
+ {
+ std::string code("import " + item->first);
+ run(code);
+ }
} catch (py::error_already_set e) {
PyErr_Print();
}
}
+py::object MussaPython::get_namespace()
+{
+ if (main_namespace.ptr() == Py_None) {
+ init_interpreter();
+ }
+ return main_namespace;
+}
+
void MussaPython::run(std::string code)
{
try {
- PyObject *global_ptr = main_namespace.ptr();
+ PyObject *global_ptr = get_namespace().ptr();
py::object result( py::handle<>(
(PyRun_String(code.c_str(), Py_file_input, global_ptr, global_ptr)
)));
py::object MussaPython::eval(std::string code)
{
try {
- PyObject *global_ptr = main_namespace.ptr();
+ PyObject *global_ptr = get_namespace().ptr();
py::object result( py::handle<>(
(PyRun_String(code.c_str(), Py_eval_input, global_ptr, global_ptr)
)));
string_vector split_name;
alg::split(split_name, name, alg::is_any_of("."));
- py::object lookup = main_namespace["__main__"];
+ py::object lookup = get_namespace()["__main__"];
for (string_vector::const_iterator name_i = split_name.begin();
name_i != split_name.end();
}
//! return a reference to a single mussa python interpreter
-MussaPython& get_py()
+MussaPython *get_py()
{
static MussaPython *py;
if (!py) {
py = new MussaPython;
}
- return *py;
+ return py;
}
\ No newline at end of file
#define _MUSSA_PYTHON_HPP_
#include <boost/python.hpp>
#include <string>
-
-extern "C" void initmussa();
-extern "C" void initmussaqui();
+#include <list>
+#include <utility>
//! Create a singleton class to manage our reference to the python interpreter
class MussaPython {
public:
+ typedef void (*python_module_init)(void);
MussaPython();
+ //! initalize interpreter
+ void init_interpreter();
+ //! add a python module that was statically compiled into this executable
+ void add_module(const std::string& name, python_module_init);
+ //! return main python namespace(initializing the interpreter if needed)
+ boost::python::object get_namespace();
//! pass multi-statement code block to the python interpreter
void run(std::string);
//! pass single expression to the python interpreter and return the result
void simple_interpreter(FILE *fp=stdin);
//! return an object in the python namespace
boost::python::object operator[](std::string);
-
protected:
+ typedef std::pair<std::string, python_module_init> module_item;
+ typedef std::list<module_item> module_list;
+ module_list python_modules;
boost::python::object main_namespace;
+
+ static void AppendInittab(const module_item &item);
};
//! return a reference to a single mussa python interpreter
-MussaPython& get_py();
+MussaPython *get_py();
#endif // _MUSSA_PYTHON_HPP_
BOOST_AUTO_TEST_CASE( execute_python )
{
- get_py().run("x = 3");
- int x = py::extract<int>(get_py().eval("x"));
+ get_py()->run("x = 3");
+ int x = py::extract<int>(get_py()->eval("x"));
BOOST_CHECK_EQUAL(x, 3);
}
BOOST_AUTO_TEST_CASE( lookup_python )
{
- get_py().run("import os");
- py::object splitext = get_py()["os.path.splitext"];
+ get_py()->run("import os");
+ py::object splitext = (*get_py())["os.path.splitext"];
py::object result = splitext("/home/diane/foo.txt");
std::string ext = py::extract<std::string>(result[1]);
BOOST_CHECK_EQUAL(ext, ".txt");
- get_py().run("from os.path import splitext");
- py::object splitext2 = get_py()["splitext"];
+ get_py()->run("from os.path import splitext");
+ py::object splitext2 = (*get_py())["splitext"];
py::object result2 = splitext("/home/diane/bar.txt");
std::string ext2 = py::extract<std::string>(result2[1]);
BOOST_CHECK_EQUAL(ext, ext2);
#ifdef USE_PYTHON
#include "py/python.hpp"
+extern "C" void initmussa();
+extern "C" void initmussaqui();
#endif
#include "qui/MussaWindow.hpp"
// allow the user to keep the interpreter open even after
// closing all the windows
app.setQuitOnLastWindowClosed(false);
- const InterpreterThread *interp = thread.create_interpreter();
+ InterpreterThread *interp = thread.create_interpreter();
+ if (!interp) {
+ std::cerr << "Unable to initialize interpeter thread" << std::endl;
+ return 1;
+ }
+ MussaPython *py = interp->get_py();
+ if (!py) {
+ std::cerr << "Unable to initialize python interpreter" << std::endl;
+ return 1;
+ }
+ py->add_module("mussa", &initmussa);
+ py->add_module("mussaqui", &initmussaqui);
// quit when the interpreter exits
QObject::connect(interp, SIGNAL(finished()),
&app, SLOT(quit()));
+ interp->start();
app.exec();
} else
#endif /* USE_PYTHON */
void InterpreterThread::run()
{
- get_py().interpreter();
+ ::get_py()->interpreter();
+}
+
+MussaPython *InterpreterThread::get_py()
+{
+ return ::get_py();
}
InterpreterThread::InterpreterThread()
#include <QThread>
+class MussaPython;
class InterpreterThread : public QThread {
Q_OBJECT
public:
void run();
+ MussaPython *get_py();
private:
//! only let ThreadManager create this object.
InterpreterThread();
get_gui_proxy();
}
-const InterpreterThread *ThreadManager::create_interpreter() {
-
+InterpreterThread *ThreadManager::create_interpreter()
+{
static QMutex interpreter_lock;
static InterpreterThread *interpreter_thread;
if (interpreter_lock.tryLock()) {
// we're the first thread
interpreter_thread = new InterpreterThread();
- interpreter_thread->start();
}
- return interpreter_thread;
// someone already started a copy of the interpreter
+ return interpreter_thread;
}
GuiProxy *ThreadManager::get_gui_proxy()
{
public:
//! make a python interpreter
- const InterpreterThread *create_interpreter();
+ InterpreterThread *create_interpreter();
static GuiProxy *get_gui_proxy();
private:
ThreadManager();