make compiled in python extension initialization more flexable
[mussa.git] / py / python.cpp
index d43ee2f74334b1f5f396aaa47a01123944d42405..75a844fbe6d9080b4111e764ab5b6e2592e8f7ee 100644 (file)
@@ -9,32 +9,60 @@ namespace py = boost::python;
 #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)
     )));
@@ -46,7 +74,7 @@ void MussaPython::run(std::string code)
 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)
     )));
@@ -93,7 +121,7 @@ py::object MussaPython::operator[](std::string name)
   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();
@@ -105,11 +133,11 @@ py::object MussaPython::operator[](std::string name)
 }
 
 //! return a reference to a single mussa python interpreter
-MussaPythonget_py()
+MussaPython *get_py()
 {
   static MussaPython *py;
   if (!py) {
     py = new MussaPython;
   }
-  return *py;
+  return py;
 }
\ No newline at end of file