提交 837a8ead877b386aebd13dd86928b3c3d6fe8bef

作者 LJH 李佳桓
1 个父辈 91f9601f

add

正在显示 1 个修改的文件 包含 283 行增加0 行删除
  1 +/**************************************************************************
  2 +* file: dmppythonutils.cpp
  3 +
  4 +* Author: wanzhongping
  5 +* Date: 2021-04-20 13:38:27
  6 +* Email: zhongpingw@chinadci.com
  7 +* copyright: 广州城市信息研究所有限公司
  8 +***************************************************************************/
  9 +
  10 +
  11 +#include "dmppythonutils.h"
  12 +#include "dmplogger.h"
  13 +#include "dmpapplication.h"
  14 +#include "../dmpserverinterface.h"
  15 +#include <boost/format.hpp>
  16 +#include <boost/algorithm/string.hpp>
  17 +#include <boost/filesystem.hpp>
  18 +
  19 +namespace python = boost::python;
  20 +
  21 +#define INIT_MODULE PyInit_dmap_server
  22 +extern "C" PyObject *INIT_MODULE();
  23 +
  24 +DmpPythonUtils::DmpPythonUtils()
  25 +{
  26 +}
  27 +
  28 +DmpPythonUtils::~DmpPythonUtils()
  29 +{
  30 + ExitPython();
  31 +}
  32 +
  33 +void DmpPythonUtils::Init()
  34 +{
  35 + if (PyImport_AppendInittab("dmap_server", INIT_MODULE) == -1)
  36 + throw std::runtime_error("Failed to add dmap_server to the interpreter's "
  37 + "builtin modules");
  38 + Py_Initialize();
  39 + python_enabled_ = true;
  40 + main_module_ = python::import("__main__");
  41 + main_namespace_ = main_module_.attr("__dict__");
  42 +}
  43 +
  44 +bool DmpPythonUtils::CheckSystemImports()
  45 +{
  46 + RunString("import sys");
  47 + RunString("import os");
  48 +
  49 + std::string pluginpaths;
  50 + std::vector<std::string> vec_paths = ExtraPluginsPaths();
  51 + std::vector<std::string>::iterator iter;
  52 + std::string comma = ",";
  53 + for (iter = vec_paths.begin(); iter != vec_paths.end(); iter++)
  54 + {
  55 + if (!boost::filesystem::exists(*iter))
  56 + {
  57 + boost::format fmt = boost::format("The extra plugin path '%1' does not exist!") % *iter;
  58 + LOGGER_WARN(fmt.str());
  59 + }
  60 +
  61 + if (!pluginpaths.empty())
  62 + {
  63 + pluginpaths += comma;
  64 + }
  65 + pluginpaths += '"' + *iter + '"';
  66 + }
  67 + if (!pluginpaths.empty())
  68 + {
  69 + pluginpaths += comma;
  70 + }
  71 + pluginpaths += '"' + HomePluginsPath() + '"';
  72 + pluginpaths += comma + '"' + PluginsPath() + '"';
  73 +
  74 + // expect that bindings are installed locally, so add the path to modules
  75 + // also add path to plugins
  76 + std::string newpaths;
  77 + newpaths += '"' + PythonPath() + '"' + comma;
  78 + newpaths += '"' + HomePythonPath() + '"' + comma;
  79 + newpaths += pluginpaths;
  80 +
  81 + RunString("sys.path = [" + newpaths + "] + sys.path");
  82 +
  83 + if (!RunString("import dmap.utils"))
  84 + {
  85 + return false;
  86 + }
  87 +
  88 + boost::format fmt_plugin_paths = boost::format("dmap.utils.plugin_paths = [%1%]") % pluginpaths;
  89 + RunString(fmt_plugin_paths.str());
  90 + boost::format fmt_sys_plugin_paths = boost::format("dmap.utils.sys_plugin_path = \"%1%\"") % PluginsPath();
  91 + RunString(fmt_sys_plugin_paths.str());
  92 + boost::format fmt_home_plugin_paths = boost::format("dmap.utils.home_plugin_path = \"%1%\"") % HomePluginsPath();
  93 + RunString(fmt_home_plugin_paths.str());
  94 +
  95 + return true;
  96 +}
  97 +
  98 +bool DmpPythonUtils::RunString(const std::string &command, bool single)
  99 +{
  100 + try
  101 + {
  102 + std::cout << command << std::endl;
  103 + if(single){
  104 + python::exec(command.c_str(), main_namespace_, main_namespace_);
  105 + }else
  106 + {
  107 + python::exec_file(command.c_str(), main_namespace_, main_namespace_);
  108 + }
  109 +
  110 + }
  111 + catch (const python::error_already_set &)
  112 + {
  113 + std::cerr << ">>> Error! Uncaught exception:\n";
  114 + PyErr_Print();
  115 + return false;
  116 + }
  117 + return true;
  118 +}
  119 +
  120 +bool DmpPythonUtils::EvalString(const std::string &command, std::string &result )
  121 +{
  122 + try
  123 + {
  124 + std::cout << command << std::endl;
  125 + python::object res = python::eval(command.c_str(), main_namespace_, main_namespace_);
  126 + result = python::extract<std::string>(res);
  127 + }
  128 + catch (const python::error_already_set &)
  129 + {
  130 + std::cerr << ">>> Error! Uncaught exception:\n";
  131 + PyErr_Print();
  132 + return false;
  133 + }
  134 + return true;
  135 +}
  136 +
  137 +
  138 +void DmpPythonUtils::InitServerPython(DmpServerInterface *interface)
  139 +{
  140 + Init();
  141 + if (!CheckSystemImports())
  142 + {
  143 + ExitPython();
  144 + return;
  145 + }
  146 +
  147 + try
  148 + {
  149 + python::import("dmap_server");
  150 + main_namespace_["serverIface_"] = boost::python::ptr(interface);
  151 + RunString("dmap.utils.initServerInterface(serverIface_)");
  152 + }
  153 + catch (python::error_already_set &e)
  154 + {
  155 + PyErr_PrintEx(0);
  156 + }
  157 + //Finish();
  158 +}
  159 +
  160 +bool DmpPythonUtils::StartServerPlugin(std::string packageName)
  161 +{
  162 + boost::format fmt = boost::format("dmap.utils.startServerPlugin('%1%')") % packageName;
  163 + try
  164 + {
  165 + std::cout << fmt.str() << std::endl;
  166 + python::object res = python::eval(fmt.str().c_str(), main_namespace_, main_namespace_);
  167 + return python::extract<bool>(res);
  168 + }
  169 + catch (const python::error_already_set &)
  170 + {
  171 + std::cerr << ">>> Error! Uncaught exception:\n";
  172 + PyErr_Print();
  173 + }
  174 + return false;
  175 +}
  176 +
  177 +void DmpPythonUtils::Finish()
  178 +{
  179 + // release GIL!
  180 + // Later on, we acquire GIL just before doing some Python calls and
  181 + // release GIL again when the work with Python API is done.
  182 + // (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
  183 + // around any calls to Python API, otherwise we may segfault!)
  184 + //main_state_ = PyEval_SaveThread();
  185 +}
  186 +
  187 +std::vector<std::string> DmpPythonUtils::ExtraPluginsPaths() const
  188 +{
  189 + std::vector<std::string> vec_paths;
  190 + const char *paths = getenv("DMAP_PLUGINPATH");
  191 + if (paths)
  192 + {
  193 + if (boost::icontains(paths, ";"))
  194 + {
  195 + boost::split(vec_paths, paths, boost::is_any_of(";"), boost::token_compress_on);
  196 + }
  197 + else
  198 + {
  199 + vec_paths.push_back(paths);
  200 + }
  201 + }
  202 + return vec_paths;
  203 +}
  204 +
  205 +std::string DmpPythonUtils::PythonPath() const
  206 +{
  207 + if (DmpApplication::IsRunningFromBuildDir())
  208 + return DmpApplication::build_output_path() + "/python";
  209 + else
  210 + return DmpApplication::pkg_data_path() + "/python";
  211 +}
  212 +
  213 +std::string DmpPythonUtils::PluginsPath() const
  214 +{
  215 + return PythonPath() + "/plugins";
  216 +}
  217 +
  218 +std::string DmpPythonUtils::HomePythonPath() const
  219 +{
  220 + std::string settingsDir = DmpApplication::DMapSettingsDirPath();
  221 + boost::format fmt = boost::format("%1%/python") % settingsDir;
  222 + return fmt.str();
  223 +}
  224 +
  225 +std::string DmpPythonUtils::HomePluginsPath() const
  226 +{
  227 + return HomePythonPath() + "/plugins";
  228 +}
  229 +
  230 +bool DmpPythonUtils::IsEnabled()
  231 +{
  232 + return python_enabled_;
  233 +}
  234 +
  235 +bool DmpPythonUtils::LoadPlugin(const std::string &packageName)
  236 +{
  237 + boost::format fmt = boost::format("dmap.utils.loadPlugin('%1%')") % packageName;
  238 + try
  239 + { std::cout << fmt.str() << std::endl;
  240 + python::object res = python::eval(fmt.str().c_str(), main_namespace_, main_namespace_);
  241 + return python::extract<bool>(res);
  242 + }
  243 + catch (const python::error_already_set &)
  244 + {
  245 + std::cerr << ">>> Error! Uncaught exception:\n";
  246 + PyErr_Print();
  247 + }
  248 + return false;
  249 +}
  250 +
  251 +void DmpPythonUtils::UninstallErrorHook()
  252 +{
  253 + RunString("qgis.utils.uninstallErrorHook()");
  254 +}
  255 +std::string DmpPythonUtils::GetPluginMetadata(const std::string &pluginName, const std::string &function)
  256 +{
  257 + std::string res;
  258 + boost::format fmt = boost::format("dmap.utils.pluginMetadata('%1%', '%2%')") % pluginName % function;
  259 + EvalString(fmt.str(), res);
  260 + LOGGER_DEBUG("metadata " + pluginName + " - '" + function + "' = " + res);
  261 + return res;
  262 +}
  263 +std::vector<std::string> DmpPythonUtils::PluginList()
  264 +{
  265 + RunString("dmap.utils.updateAvailablePlugins()");
  266 +
  267 + std::string output;
  268 + EvalString("'\\n'.join(dmap.utils.available_plugins)", output);
  269 +
  270 + std::vector<std::string> vec_plugins;
  271 + boost::split(vec_plugins, output, boost::is_any_of("\n"), boost::token_compress_on);
  272 + return vec_plugins;
  273 +}
  274 +void DmpPythonUtils::ExitPython()
  275 +{
  276 + if (error_hook_installed_)
  277 + UninstallErrorHook();
  278 + // causes segfault!
  279 + //Py_Finalize();
  280 + // main_module_ = nullptr;
  281 + // main_dict_ = nullptr;
  282 + python_enabled_ = false;
  283 +}
\ No newline at end of file
... ...
注册登录 后发表评论