|
ferencd@0
|
1 #ifndef PYTHON_RUNNER_H
|
|
ferencd@0
|
2 #define PYTHON_RUNNER_H
|
|
ferencd@0
|
3
|
|
ferencd@0
|
4 #ifdef PYTHON_SCRIPTING
|
|
ferencd@0
|
5 #include "pyembed.h"
|
|
ferencd@0
|
6 #endif
|
|
ferencd@0
|
7
|
|
ferencd@0
|
8 #include <map>
|
|
ferencd@0
|
9 #include <string>
|
|
ferencd@0
|
10 #include <set>
|
|
ferencd@0
|
11
|
|
ferencd@0
|
12 struct python_runner
|
|
ferencd@0
|
13 {
|
|
ferencd@0
|
14
|
|
ferencd@0
|
15 PyObject* pymodule = nullptr;
|
|
ferencd@0
|
16 PyObject *main = nullptr;
|
|
ferencd@0
|
17
|
|
ferencd@0
|
18 std::string buffer;
|
|
ferencd@0
|
19
|
|
ferencd@0
|
20 explicit python_runner()
|
|
ferencd@0
|
21 {
|
|
ferencd@0
|
22 PyImport_AppendInittab("emb", emb::PyInit_emb);
|
|
ferencd@0
|
23 Py_Initialize();
|
|
ferencd@0
|
24
|
|
ferencd@0
|
25 pymodule = PyImport_ImportModule("emb");
|
|
ferencd@0
|
26 main = PyImport_AddModule("__main__");
|
|
ferencd@0
|
27 }
|
|
ferencd@0
|
28
|
|
ferencd@0
|
29 std::string run(std::map<std::string, std::string>& kps, std::string between, const std::vector<std::string>& all_variables)
|
|
ferencd@0
|
30 {
|
|
ferencd@0
|
31 std::string buffer;
|
|
ferencd@0
|
32 emb::stdout_write_type write = [&buffer] (std::string s) { buffer += s; };
|
|
ferencd@0
|
33 emb::set_stdout(write);
|
|
ferencd@0
|
34
|
|
ferencd@0
|
35 // generate a list of assignments to kp/kv values from the kps vector
|
|
ferencd@0
|
36 std::set<std::string> set_variables;
|
|
ferencd@0
|
37 for(const auto& [kp, kv] : kps)
|
|
ferencd@0
|
38 {
|
|
ferencd@0
|
39 std::string cmd = kp + "='" + kv + "'\n";
|
|
ferencd@0
|
40 between = cmd + between;
|
|
ferencd@0
|
41 set_variables.insert(kp);
|
|
ferencd@0
|
42 }
|
|
ferencd@0
|
43
|
|
ferencd@0
|
44 // here gather all the other variables that might have been in the template
|
|
ferencd@0
|
45 for(const auto& v : all_variables)
|
|
ferencd@0
|
46 {
|
|
ferencd@0
|
47 if(set_variables.count(v) == 0)
|
|
ferencd@0
|
48 {
|
|
ferencd@0
|
49 std::string cmd = v + "=''\n";
|
|
ferencd@0
|
50 between = cmd + between;
|
|
ferencd@0
|
51 set_variables.insert(v);
|
|
ferencd@0
|
52 }
|
|
ferencd@0
|
53 }
|
|
ferencd@0
|
54
|
|
ferencd@0
|
55 // now gather all the structure definitions
|
|
ferencd@0
|
56
|
|
ferencd@0
|
57 //std::cerr << "Trying to run:" << std::endl<< between << std::endl;
|
|
ferencd@0
|
58
|
|
ferencd@0
|
59 PyRun_SimpleString(between.c_str());
|
|
ferencd@0
|
60 emb::reset_stdout();
|
|
ferencd@0
|
61
|
|
ferencd@0
|
62 PyObject *globals = PyModule_GetDict(main);
|
|
ferencd@0
|
63 if(globals)
|
|
ferencd@0
|
64 {
|
|
ferencd@0
|
65 for(const auto& v : set_variables)
|
|
ferencd@0
|
66 {
|
|
ferencd@0
|
67 PyObject *a = PyDict_GetItemString(globals, v.c_str());
|
|
ferencd@0
|
68 if(a)
|
|
ferencd@0
|
69 {
|
|
ferencd@0
|
70 PyObject* temp_bytes = PyUnicode_AsEncodedString( a, "UTF-8", "strict" );
|
|
ferencd@0
|
71 if (temp_bytes)
|
|
ferencd@0
|
72 {
|
|
ferencd@0
|
73 std::string r = PyBytes_AS_STRING( temp_bytes );
|
|
ferencd@0
|
74 kps[v] = r;
|
|
ferencd@0
|
75
|
|
ferencd@0
|
76 Py_DECREF( temp_bytes );
|
|
ferencd@0
|
77 }
|
|
ferencd@0
|
78 Py_DECREF(a);
|
|
ferencd@0
|
79 }
|
|
ferencd@0
|
80 }
|
|
ferencd@0
|
81
|
|
ferencd@0
|
82 Py_DECREF(globals);
|
|
ferencd@0
|
83 }
|
|
ferencd@0
|
84
|
|
ferencd@0
|
85 return buffer;
|
|
ferencd@0
|
86 }
|
|
ferencd@0
|
87
|
|
ferencd@0
|
88 virtual ~python_runner()
|
|
ferencd@0
|
89 {
|
|
ferencd@0
|
90 Py_DECREF(main);
|
|
ferencd@0
|
91 Py_DECREF(pymodule);
|
|
ferencd@0
|
92 Py_Finalize();
|
|
ferencd@0
|
93 }
|
|
ferencd@0
|
94
|
|
ferencd@0
|
95 };
|
|
ferencd@0
|
96
|
|
ferencd@0
|
97 #endif // PYTHON_RUNNER_H
|