Salome HOME
Merge branch 'master' into omu/launcher_ssl
[modules/kernel.git] / src / Container / SALOME_CPythonHelper.cxx
1 // Copyright (C) 2019-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony GEAY (EDF R&D)
20
21 #include "SALOME_CPythonHelper.hxx"
22
23 SALOME_CPythonHelper *SALOME_CPythonHelper::_CPYTHONHELPER_INSTANCE = nullptr;
24
25 #if PY_VERSION_HEX < 0x03050000
26 static char*
27 Py_EncodeLocale(const wchar_t *arg, size_t *size)
28 {
29   return _Py_wchar2char(arg, size);
30 }
31 static wchar_t*
32 Py_DecodeLocale(const char *arg, size_t *size)
33 {
34   return _Py_char2wchar(arg, size);
35 }
36 #endif
37
38 SALOME_CPythonHelper *SALOME_CPythonHelper::Singleton()
39 {
40   if(!_CPYTHONHELPER_INSTANCE)
41     _CPYTHONHELPER_INSTANCE = new SALOME_CPythonHelper;
42   return _CPYTHONHELPER_INSTANCE;
43 }
44
45 void SALOME_CPythonHelper::KillSingleton()
46 {
47   delete _CPYTHONHELPER_INSTANCE;
48   _CPYTHONHELPER_INSTANCE = nullptr;
49 }
50
51 void SALOME_CPythonHelper::initializePython(int argc, char *argv[])
52 {
53   Py_Initialize();
54 #if PY_VERSION_HEX < 0x03070000
55   PyEval_InitThreads();
56 #endif
57   wchar_t **changed_argv = new wchar_t*[argc]; // Setting arguments
58   for (int i = 0; i < argc; i++)
59     changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
60   PySys_SetArgv(argc, changed_argv);
61   PyObject *mainmod(PyImport_AddModule("__main__"));
62   _globals=PyModule_GetDict(mainmod);
63   if(PyDict_GetItemString(_globals, "__builtins__") == NULL)
64     {
65       PyObject *bimod(PyImport_ImportModule("__builtin__"));
66       if (bimod == NULL || PyDict_SetItemString(_globals, "__builtins__", bimod) != 0)
67         Py_FatalError("can't add __builtins__ to __main__");
68       Py_XDECREF(bimod);
69     }
70   _locals=PyDict_New();
71   PyObject *tmp(PyList_New(0));
72   _pickler=PyImport_ImportModuleLevel(const_cast<char *>("pickle"),_globals,_locals,tmp,0);
73   _subprocess=PyImport_ImportModuleLevel(const_cast<char *>("subprocess"),_globals,_locals,tmp,0);
74   PyObject *socket(PyImport_ImportModuleLevel(const_cast<char *>("socket"),_globals,_locals,tmp,0));
75   PyDict_SetItemString(_globals,"sp",_subprocess);
76   PyDict_SetItemString(_globals,"socket",socket);
77 }
78
79 void SALOME_CPythonHelper::registerToSalomePiDict(const std::string& processName, long pid) const
80 {
81   PyObject *mod(PyImport_ImportModule("addToKillList"));//new value
82   if(!mod)
83     return;
84   PyObject *meth(PyObject_GetAttrString(mod,"addToKillList"));//new value
85   if(!meth)
86     { Py_XDECREF(mod); return ; }
87   PyObject *args(PyTuple_New(2));
88   PyTuple_SetItem(args,0,PyLong_FromLong(pid));
89   PyTuple_SetItem(args,1,PyUnicode_FromString(processName.c_str()));
90   PyObject *res(PyObject_CallObject(meth,args));
91   Py_XDECREF(args);
92   Py_XDECREF(res);
93   Py_XDECREF(meth);
94   Py_XDECREF(mod);
95 }
96
97 std::vector<long> SALOME_CPythonHelper::evalVL(const std::string& pyCode) const
98 {
99   PyObject* code(Py_CompileString(pyCode.c_str(),"evalVL.py", Py_eval_input));
100   PyObject *res(PyEval_EvalCode( code, _globals, _locals));
101   Py_DECREF(code);
102   Py_ssize_t n(PyList_Size(res));
103   std::vector<long> ret(n);
104   for(auto i = 0; i<n; ++i)
105     {
106       PyObject *elt(PyList_GetItem(res,i));//borrowed
107       ret[i]=PyLong_AsLong(elt);
108     }
109   Py_DECREF(res);
110   return ret;
111 }
112
113 std::string SALOME_CPythonHelper::evalS(const std::string& pyCode) const
114 {
115   PyObject* code(Py_CompileString(pyCode.c_str(),"evalS.py", Py_eval_input));
116   PyObject *res(PyEval_EvalCode( code, _globals, _locals));
117   Py_DECREF(code);
118   std::string ret(PyUnicode_AsUTF8(res));
119   Py_DECREF(res);
120   return ret;
121 }
122
123
124 SALOME_CPythonHelper::~SALOME_CPythonHelper()
125 {
126   // _globals is borrowed ref -> do nothing
127
128   /*if(_locals){ auto refcount_locals = Py_REFCNT(_locals); }*/
129   
130   Py_XDECREF(_locals);
131   Py_XDECREF(_pickler);
132 }