Flow123d
python_loader.cc
Go to the documentation of this file.
1 /*
2  * python_loader.cc
3  *
4  * Created on: Aug 31, 2012
5  * Author: jb
6  */
7 
8 
9 #ifdef HAVE_PYTHON
10 
11 #include "system/python_loader.hh"
12 #include "global_defs.h"
13 #include "system/system.hh"
14 #include <string>
15 #include <iostream>
16 #include <fstream>
17 #include <sstream>
18 
19 PyObject * PythonLoader::load_module_from_file(const std::string& fname) {
20  // don't know direct way how to load module form file, so we read it into string and use load_module_from_string
21  std::ifstream file_stream( fname.c_str() );
22  // check correct openning
23  INPUT_CHECK(! file_stream.fail(), "Can not open input file '%s'.\n", fname.c_str() );
24  file_stream.exceptions ( ifstream::failbit | ifstream::badbit );
25 
26  std::stringstream buffer;
27  buffer << file_stream.rdbuf();
28 
29  string module_name;
30  unsigned int pos = fname.rfind("/");
31  if (pos != string::npos)
32  module_name = fname.substr(pos+1);
33  else
34  module_name = fname;
35 
36  // cout << "python module: " << module_name <<endl;
37  // DBGMSG("%s\n", buffer.str().c_str());
38  // TODO: use exceptions and catch it here to produce shorter and more precise error message
39  return load_module_from_string(module_name, buffer.str() );
40 }
41 
42 
43 
44 PyObject * PythonLoader::load_module_from_string(const std::string& module_name, const std::string& source_string) {
45 
46  // for unknown reason module name is non-const, so we have to make char * copy
47  char * tmp_name = new char[ module_name.size() + 2 ];
48  strcpy( tmp_name, module_name.c_str() );
49  PyObject * result = PyImport_ExecCodeModule(tmp_name,
50  Py_CompileString( source_string.c_str(), "flow123d_python_loader", Py_file_input ) );
51 
52  if (result == NULL) {
53  PyErr_Print();
54  std::cerr << "Error: Can not load python module '" << module_name << "' from string:" << std::endl;
55  std::cerr << source_string << std::endl;
56  }
57 
58  delete[] tmp_name;
59  return result;
60 }
61 
62 
63 internal::PythonRunning PythonLoader::py_running;
64 
65 
66 namespace internal {
67 
68 PythonRunning::PythonRunning() {
69  Py_Initialize();
70 }
71 
72 
73 
74 PythonRunning::~PythonRunning() {
75  Py_Finalize();
76 }
77 
78 } // close namespace internal
79 
80 #endif // HAVE_PYTHON