FreeCAD

Форк
0
/
Interpreter.cpp 
1005 строк · 30.2 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de>              *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This program is free software; you can redistribute it and/or modify  *
7
 *   it under the terms of the GNU Library General Public License (LGPL)   *
8
 *   as published by the Free Software Foundation; either version 2 of     *
9
 *   the License, or (at your option) any later version.                   *
10
 *   for detail see the LICENCE text file.                                 *
11
 *                                                                         *
12
 *   FreeCAD is distributed in the hope that it will be useful,            *
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15
 *   GNU Library General Public License for more details.                  *
16
 *                                                                         *
17
 *   You should have received a copy of the GNU Library General Public     *
18
 *   License along with FreeCAD; if not, write to the Free Software        *
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
20
 *   USA                                                                   *
21
 *                                                                         *
22
 ***************************************************************************/
23

24

25
#include "PreCompiled.h"
26

27
#ifndef _PreComp_
28
#include <sstream>
29
#include <boost/regex.hpp>
30
#endif
31

32
#include "Interpreter.h"
33
#include "Console.h"
34
#include "ExceptionFactory.h"
35
#include "FileInfo.h"
36
#include "PyObjectBase.h"
37
#include "PyTools.h"
38
#include "Stream.h"
39

40

41
char format2[1024];  // Warning! Can't go over 512 characters!!!
42
unsigned int format2_len = 1024;
43

44
using namespace Base;
45

46
PyException::PyException(const Py::Object& obj)
47
{
48
    _sErrMsg = obj.as_string();
49
    // WARNING: we are assuming that python type object will never be
50
    // destroyed, so we don't keep reference here to save book-keeping in
51
    // our copy constructor and destructor
52
    // NOLINTBEGIN
53
    _exceptionType = reinterpret_cast<PyObject*>(obj.ptr()->ob_type);
54
    _errorType = obj.ptr()->ob_type->tp_name;
55
    // NOLINTEND
56
}
57

58
PyException::PyException()
59
{
60
    PP_Fetch_Error_Text(); /* fetch (and clear) exception */
61

62
    setPyObject(PP_PyDict_Object);
63

64
    std::string prefix = PP_last_error_type; /* exception name text */
65
    std::string error = PP_last_error_info;  /* exception data text */
66

67
    _sErrMsg = error;
68
    _errorType = prefix;
69

70
    // NOLINTNEXTLINE
71
    _exceptionType = PP_last_exception_type;
72

73
    if (PP_last_exception_type) {
74
        // WARNING: we are assuming that python type object will never be
75
        // destroyed, so we don't keep reference here to save book-keeping in
76
        // our copy constructor and destructor
77
        Py_DECREF(PP_last_exception_type);
78
        PP_last_exception_type = nullptr;
79
    }
80

81
    _stackTrace = PP_last_error_trace; /* exception traceback text */
82

83
    // This should be done in the constructor because when doing
84
    // in the destructor it's not always clear when it is called
85
    // and thus may clear a Python exception when it should not.
86
    PyGILStateLocker locker;
87
    PyErr_Clear();  // must be called to keep Python interpreter in a valid state (Werner)
88
}
89

90
PyException::~PyException() noexcept = default;
91

92
void PyException::ThrowException()
93
{
94
    PyException myexcp;
95
    myexcp.ReportException();
96
    myexcp.raiseException();
97
}
98

99
void PyException::raiseException()
100
{
101
    PyGILStateLocker locker;
102
    if (PP_PyDict_Object) {
103
        // delete the Python dict upon destruction of edict
104
        Py::Dict edict(PP_PyDict_Object, true);
105
        PP_PyDict_Object = nullptr;
106

107
        std::string exceptionname;
108
        if (_exceptionType == Base::PyExc_FC_FreeCADAbort) {
109
            edict.setItem("sclassname", Py::String(typeid(Base::AbortException).name()));
110
        }
111
        if (_isReported) {
112
            edict.setItem("breported", Py::True());
113
        }
114
        Base::ExceptionFactory::Instance().raiseException(edict.ptr());
115
    }
116

117
    if (_exceptionType == Base::PyExc_FC_FreeCADAbort) {
118
        Base::AbortException exc(_sErrMsg.c_str());
119
        exc.setReported(_isReported);
120
        throw exc;
121
    }
122

123
    throw *this;
124
}
125

126
void PyException::ReportException() const
127
{
128
    if (!_isReported) {
129
        _isReported = true;
130
        // set sys.last_vars to make post-mortem debugging work
131
        PyGILStateLocker locker;
132
        PySys_SetObject("last_traceback", PP_last_traceback);
133
        Base::Console().DeveloperError("pyException",
134
                                       "%s%s: %s\n",
135
                                       _stackTrace.c_str(),
136
                                       _errorType.c_str(),
137
                                       what());
138
    }
139
}
140

141
void PyException::setPyException() const
142
{
143
    std::stringstream str;
144
    str << getStackTrace() << getErrorType() << ": " << what();
145
    PyErr_SetString(getPyExceptionType(), str.str().c_str());
146
}
147

148
// ---------------------------------------------------------
149

150
SystemExitException::SystemExitException()
151
{
152
    // Set exception message and code based upon the python sys.exit() code and/or message
153
    // based upon the following sys.exit() call semantics.
154
    //
155
    // Invocation       |  _exitCode  |  _sErrMsg
156
    // ---------------- +  ---------  +  --------
157
    // sys.exit(int#)   |   int#      |   "System Exit"
158
    // sys.exit(string) |   1         |   string
159
    // sys.exit()       |   1         |   "System Exit"
160

161
    long int errCode = 1;
162
    std::string errMsg = "System exit";
163
    PyObject* type {};
164
    PyObject* value {};
165
    PyObject* traceback {};
166
    PyObject* code {};
167

168
    PyGILStateLocker locker;
169
    PyErr_Fetch(&type, &value, &traceback);
170
    PyErr_NormalizeException(&type, &value, &traceback);
171

172
    if (value) {
173
        code = PyObject_GetAttrString(value, "code");
174
        if (code && value != Py_None) {
175
            Py_DECREF(value);
176
            value = code;
177
        }
178

179
        if (PyLong_Check(value)) {
180
            errCode = PyLong_AsLong(value);
181
        }
182
        else {
183
            const char* str = PyUnicode_AsUTF8(value);
184
            if (str) {
185
                errMsg = errMsg + ": " + str;
186
            }
187
        }
188
    }
189

190
    _sErrMsg = errMsg;
191
    _exitCode = errCode;
192
}
193

194
// ---------------------------------------------------------
195

196
// Fixes #0000831: python print causes File descriptor error on windows
197
// NOLINTNEXTLINE
198
class PythonStdOutput: public Py::PythonExtension<PythonStdOutput>
199
{
200
public:
201
    static void init_type()
202
    {
203
        behaviors().name("PythonStdOutput");
204
        behaviors().doc("Python standard output");
205
        add_varargs_method("write", &PythonStdOutput::write, "write()");
206
        add_varargs_method("flush", &PythonStdOutput::flush, "flush()");
207
    }
208

209
    PythonStdOutput() = default;
210
    ~PythonStdOutput() override = default;
211

212
    Py::Object write(const Py::Tuple&)
213
    {
214
        return Py::None();
215
    }
216
    Py::Object flush(const Py::Tuple&)
217
    {
218
        return Py::None();
219
    }
220
};
221

222
// ---------------------------------------------------------
223

224
InterpreterSingleton::InterpreterSingleton()
225
{
226
    this->_global = nullptr;
227
}
228

229
InterpreterSingleton::~InterpreterSingleton() = default;
230

231

232
std::string InterpreterSingleton::runString(const char* sCmd)
233
{
234
    PyObject* module {};
235
    PyObject* dict {};
236
    PyObject* presult {};
237

238
    PyGILStateLocker locker;
239
    module = PP_Load_Module("__main__"); /* get module, init python */
240
    if (!module) {
241
        throw PyException(); /* not incref'd */
242
    }
243
    dict = PyModule_GetDict(module); /* get dict namespace */
244
    if (!dict) {
245
        throw PyException(); /* not incref'd */
246
    }
247

248

249
    presult = PyRun_String(sCmd, Py_file_input, dict, dict); /* eval direct */
250
    if (!presult) {
251
        if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
252
            throw SystemExitException();
253
        }
254

255
        PyException::ThrowException();
256
        return {};  // just to quieten code analyzers
257
    }
258

259
    PyObject* repr = PyObject_Repr(presult);
260
    Py_DECREF(presult);
261
    if (repr) {
262
        std::string ret(PyUnicode_AsUTF8(repr));
263
        Py_DECREF(repr);
264
        return ret;
265
    }
266

267
    PyErr_Clear();
268
    return {};
269
}
270

271
/** runStringWithKey(psCmd, key, key_initial_value)
272
 * psCmd is python script to run
273
 * key is the name of a python string variable the script will have read/write
274
 * access to during script execution.  It will be our return value.
275
 * key_initial_value is the initial value c++ will set before calling the script
276
 * If the script runs successfully it will be able to change the value of key as
277
 * the return value, but if there is a runtime error key will not be changed even
278
 * if the error occurs after changing it inside the script.
279
 */
280

281
std::string InterpreterSingleton::runStringWithKey(const char* psCmd,
282
                                                   const char* key,
283
                                                   const char* key_initial_value)
284
{
285
    PyGILStateLocker locker;
286
    Py::Module module("__main__");
287
    Py::Dict globalDictionary = module.getDict();
288
    Py::Dict localDictionary;
289
    Py::String initial_value(key_initial_value);
290
    localDictionary.setItem(key, initial_value);
291

292
    PyObject* presult =
293
        PyRun_String(psCmd, Py_file_input, globalDictionary.ptr(), localDictionary.ptr());
294
    if (!presult) {
295
        if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
296
            throw SystemExitException();
297
        }
298

299
        PyException::ThrowException();
300
        return {};  // just to quieten code analyzers
301
    }
302
    Py_DECREF(presult);
303

304
    Py::Object key_return_value = localDictionary.getItem(key);
305
    if (!key_return_value.isString()) {
306
        key_return_value = key_return_value.str();  // NOLINT
307
    }
308

309
    Py::Bytes str = Py::String(key_return_value).encode("utf-8", "~E~");
310
    std::string result = static_cast<std::string>(str);
311
    return result;
312
}
313

314
Py::Object InterpreterSingleton::runStringObject(const char* sCmd)
315
{
316
    PyObject* module {};
317
    PyObject* dict {};
318
    PyObject* presult {};
319

320
    PyGILStateLocker locker;
321
    module = PP_Load_Module("__main__"); /* get module, init python */
322
    if (!module) {
323
        throw PyException(); /* not incref'd */
324
    }
325
    dict = PyModule_GetDict(module); /* get dict namespace */
326
    if (!dict) {
327
        throw PyException(); /* not incref'd */
328
    }
329

330

331
    presult = PyRun_String(sCmd, Py_eval_input, dict, dict); /* eval direct */
332
    if (!presult) {
333
        if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
334
            throw SystemExitException();
335
        }
336

337
        throw PyException();
338
    }
339

340
    return Py::asObject(presult);
341
}
342

343
void InterpreterSingleton::systemExit()
344
{
345
    /* This code is taken from the original Python code */
346
    PyObject* exception {};
347
    PyObject* value {};
348
    PyObject* tb {};
349
    int exitcode = 0;
350

351
    PyErr_Fetch(&exception, &value, &tb);
352
    fflush(stdout);
353
    if (!value || value == Py_None) {
354
        goto done;  // NOLINT
355
    }
356
    if (PyExceptionInstance_Check(value)) {
357
        /* The error code should be in the `code' attribute. */
358
        PyObject* code = PyObject_GetAttrString(value, "code");
359
        if (code) {
360
            Py_DECREF(value);
361
            value = code;
362
            if (value == Py_None) {
363
                goto done;  // NOLINT
364
            }
365
        }
366
        /* If we failed to dig out the 'code' attribute,
367
           just let the else clause below print the error. */
368
    }
369
    if (PyLong_Check(value)) {
370
        exitcode = (int)PyLong_AsLong(value);
371
    }
372
    else {
373
        PyObject_Print(value, stderr, Py_PRINT_RAW);
374
        PySys_WriteStderr("\n");
375
        exitcode = 1;
376
    }
377
done:
378
    /* Restore and clear the exception info, in order to properly decref
379
     * the exception, value, and traceback.  If we just exit instead,
380
     * these leak, which confuses PYTHONDUMPREFS output, and may prevent
381
     * some finalizers from running.
382
     */
383
    PyErr_Restore(exception, value, tb);
384
    PyErr_Clear();
385
    Py_Exit(exitcode);
386
    /* NOTREACHED */
387
}
388

389
void InterpreterSingleton::runInteractiveString(const char* sCmd)
390
{
391
    PyObject* module {};
392
    PyObject* dict {};
393
    PyObject* presult {};
394

395
    PyGILStateLocker locker;
396
    module = PP_Load_Module("__main__"); /* get module, init python */
397
    if (!module) {
398
        throw PyException(); /* not incref'd */
399
    }
400
    dict = PyModule_GetDict(module); /* get dict namespace */
401
    if (!dict) {
402
        throw PyException(); /* not incref'd */
403
    }
404

405
    presult = PyRun_String(sCmd, Py_single_input, dict, dict); /* eval direct */
406
    if (!presult) {
407
        if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
408
            throw SystemExitException();
409
        }
410
        /* get latest python exception information */
411
        /* and print the error to the error output */
412
        PyObject* errobj {};
413
        PyObject* errdata {};
414
        PyObject* errtraceback {};
415
        PyErr_Fetch(&errobj, &errdata, &errtraceback);
416

417
        RuntimeError exc("");  // do not use PyException since this clears the error indicator
418
        if (errdata) {
419
            if (PyUnicode_Check(errdata)) {
420
                exc.setMessage(PyUnicode_AsUTF8(errdata));
421
            }
422
        }
423
        PyErr_Restore(errobj, errdata, errtraceback);
424
        if (PyErr_Occurred()) {
425
            PyErr_Print();
426
        }
427
        throw exc;
428
    }
429

430
    Py_DECREF(presult);
431
}
432

433
void InterpreterSingleton::runFile(const char* pxFileName, bool local)
434
{
435
#ifdef FC_OS_WIN32
436
    FileInfo fi(pxFileName);
437
    FILE* fp = _wfopen(fi.toStdWString().c_str(), L"r");
438
#else
439
    FILE* fp = fopen(pxFileName, "r");
440
#endif
441
    if (!fp) {
442
        throw FileException("Unknown file", pxFileName);
443
    }
444

445
    PyGILStateLocker locker;
446
    PyObject* module {};
447
    PyObject* dict {};
448
    module = PyImport_AddModule("__main__");
449
    dict = PyModule_GetDict(module);
450
    if (local) {
451
        dict = PyDict_Copy(dict);
452
    }
453
    else {
454
        Py_INCREF(dict);  // avoid to further distinguish between local and global dict
455
    }
456

457
    if (!PyDict_GetItemString(dict, "__file__")) {
458
        PyObject* pyObj = PyUnicode_FromString(pxFileName);
459
        if (!pyObj) {
460
            fclose(fp);
461
            Py_DECREF(dict);
462
            return;
463
        }
464
        if (PyDict_SetItemString(dict, "__file__", pyObj) < 0) {
465
            Py_DECREF(pyObj);
466
            fclose(fp);
467
            Py_DECREF(dict);
468
            return;
469
        }
470
        Py_DECREF(pyObj);
471
    }
472

473
    PyObject* result = PyRun_File(fp, pxFileName, Py_file_input, dict, dict);
474
    fclose(fp);
475
    Py_DECREF(dict);
476

477
    if (!result) {
478
        if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
479
            throw SystemExitException();
480
        }
481
        throw PyException();
482
    }
483
    Py_DECREF(result);
484
}
485

486
bool InterpreterSingleton::loadModule(const char* psModName)
487
{
488
    // buffer acrobatics
489
    // PyBuf ModName(psModName);
490
    PyObject* module {};
491

492
    PyGILStateLocker locker;
493
    module = PP_Load_Module(psModName);
494

495
    if (!module) {
496
        if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
497
            throw SystemExitException();
498
        }
499

500
        throw PyException();
501
    }
502

503
    return true;
504
}
505

506
PyObject* InterpreterSingleton::addModule(Py::ExtensionModuleBase* mod)
507
{
508
    _modules.push_back(mod);
509
    return mod->module().ptr();
510
}
511

512
void InterpreterSingleton::cleanupModules()
513
{
514
    // This is only needed to make the address sanitizer happy
515
#if defined(__has_feature)
516
#if __has_feature(address_sanitizer)
517
    for (auto it : _modules) {
518
        delete it;
519
    }
520
    _modules.clear();
521
#endif
522
#endif
523
}
524

525
void InterpreterSingleton::addType(PyTypeObject* Type, PyObject* Module, const char* Name)
526
{
527
    // NOTE: To finish the initialization of our own type objects we must
528
    // call PyType_Ready, otherwise we run into a segmentation fault, later on.
529
    // This function is responsible for adding inherited slots from a type's base class.
530
    if (PyType_Ready(Type) < 0) {
531
        return;
532
    }
533
    PyModule_AddObject(Module, Name, Base::getTypeAsObject(Type));
534
}
535

536
void InterpreterSingleton::addPythonPath(const char* Path)
537
{
538
    PyGILStateLocker locker;
539
    Py::List list(PySys_GetObject("path"));
540
    list.append(Py::String(Path));
541
}
542

543
#if PY_VERSION_HEX < 0x030b0000
544
const char* InterpreterSingleton::init(int argc, char* argv[])
545
{
546
    if (!Py_IsInitialized()) {
547
        Py_SetProgramName(Py_DecodeLocale(argv[0], nullptr));
548
        // There is a serious bug in VS from 2010 until 2013 where the file descriptor for stdin,
549
        // stdout or stderr returns a valid value for GUI applications (i.e. subsystem = Windows)
550
        // where it shouldn't. This causes Python to fail during initialization. A workaround is to
551
        // use freopen on stdin, stdout and stderr. See the class Redirection inside main()
552
        // https://bugs.python.org/issue17797#msg197474
553
        //
554
        Py_Initialize();
555
        const char* virtualenv = getenv("VIRTUAL_ENV");
556
        if (virtualenv) {
557
            PyRun_SimpleString(
558
                "# Check for virtualenv, and activate if present.\n"
559
                "# See "
560
                "https://virtualenv.pypa.io/en/latest/userguide/"
561
                "#using-virtualenv-without-bin-python\n"
562
                "import os\n"
563
                "import sys\n"
564
                "base_path = os.getenv(\"VIRTUAL_ENV\")\n"
565
                "if not base_path is None:\n"
566
                "    activate_this = os.path.join(base_path, \"bin\", \"activate_this.py\")\n"
567
                "    exec(open(activate_this).read(), {'__file__':activate_this})\n");
568
        }
569

570
#if PY_VERSION_HEX < 0x03090000
571
        PyEval_InitThreads();
572
#endif
573

574
        size_t size = argc;
575
        static std::vector<wchar_t*> _argv(size);
576
        for (int i = 0; i < argc; i++) {
577
            _argv[i] = Py_DecodeLocale(argv[i], nullptr);
578
        }
579
        PySys_SetArgv(argc, _argv.data());
580
        PythonStdOutput::init_type();
581
        this->_global = PyEval_SaveThread();
582
    }
583

584
    PyGILStateLocker lock;
585
    return Py_EncodeLocale(Py_GetPath(), nullptr);
586
}
587
#else
588
namespace
589
{
590
void initInterpreter(int argc, char* argv[])
591
{
592
    PyStatus status;
593
    PyConfig config;
594
    PyConfig_InitIsolatedConfig(&config);
595
    config.isolated = 0;
596
    config.user_site_directory = 1;
597

598
    status = PyConfig_SetBytesArgv(&config, argc, argv);
599
    if (PyStatus_Exception(status)) {
600
        throw Base::RuntimeError("Failed to set config");
601
    }
602

603
    status = Py_InitializeFromConfig(&config);
604
    if (PyStatus_Exception(status)) {
605
        throw Base::RuntimeError("Failed to init from config");
606
    }
607

608
    // If FreeCAD was run from within a Python virtual environment, ensure that the site-packages
609
    // directory from that environment is used.
610
    const char* virtualenv = getenv("VIRTUAL_ENV");
611
    if (virtualenv) {
612
        std::wstringstream ss;
613
        PyConfig_Read(&config);
614
        ss << virtualenv << L"/lib/python" << PY_MAJOR_VERSION << "." << PY_MINOR_VERSION
615
           << "/site-packages";
616
        PyObject* venvLocation = PyUnicode_FromWideChar(ss.str().c_str(), ss.str().size());
617
        PyObject* path = PySys_GetObject("path");
618
        PyList_Append(path, venvLocation);
619
    }
620

621
    PyConfig_Clear(&config);
622

623
    Py_Initialize();
624
}
625
}  // namespace
626
const char* InterpreterSingleton::init(int argc, char* argv[])
627
{
628
    try {
629
        if (!Py_IsInitialized()) {
630
            initInterpreter(argc, argv);
631

632
            PythonStdOutput::init_type();
633
            this->_global = PyEval_SaveThread();
634
        }
635

636
        PyGILStateLocker lock;
637
        return Py_EncodeLocale(Py_GetPath(), nullptr);
638
    }
639
    catch (const Base::Exception& e) {
640
        e.ReportException();
641
        throw;
642
    }
643
}
644
#endif
645

646
void InterpreterSingleton::replaceStdOutput()
647
{
648
    PyGILStateLocker locker;
649
    PythonStdOutput* out = new PythonStdOutput();
650
    PySys_SetObject("stdout", out);
651
    PySys_SetObject("stderr", out);
652
}
653

654
int InterpreterSingleton::cleanup(void (*func)())
655
{
656
    return Py_AtExit(func);
657
}
658

659
void InterpreterSingleton::finalize()
660
{
661
    try {
662
        PyEval_RestoreThread(this->_global);
663
        cleanupModules();
664
        Py_Finalize();
665
    }
666
    catch (...) {
667
    }
668
}
669

670
void InterpreterSingleton::runStringArg(const char* psCom, ...)
671
{
672
    // va stuff
673
    va_list namelessVars;
674
    va_start(namelessVars, psCom);  // Get the "..." vars
675
    int len = vsnprintf(format2, format2_len, psCom, namelessVars);
676
    va_end(namelessVars);
677
    if (len == -1) {
678
        // argument too long
679
        assert(false);
680
    }
681

682
    runString(format2);
683
}
684

685

686
// Singleton:
687

688
InterpreterSingleton* InterpreterSingleton::_pcSingleton = nullptr;
689

690
InterpreterSingleton& InterpreterSingleton::Instance()
691
{
692
    // not initialized!
693
    if (!_pcSingleton) {
694
        _pcSingleton = new InterpreterSingleton();
695
    }
696
    return *_pcSingleton;
697
}
698

699
void InterpreterSingleton::Destruct()
700
{
701
    // not initialized or double destruct!
702
    assert(_pcSingleton);
703
    delete _pcSingleton;
704
    _pcSingleton = nullptr;
705
}
706

707
int InterpreterSingleton::runCommandLine(const char* prompt)
708
{
709
    PyGILStateLocker locker;
710
    return PP_Run_Command_Line(prompt);
711
}
712

713
/**
714
 *  Runs a member method of an object with no parameter and no return value
715
 *  void (void). There are other methods to run with returns
716
 */
717
void InterpreterSingleton::runMethodVoid(PyObject* pobject, const char* method)
718
{
719
    PyGILStateLocker locker;
720
    if (PP_Run_Method(pobject,  // object
721
                      method,   // run method
722
                      nullptr,  // no return type
723
                      nullptr,  // so no return object
724
                      "()")     // no arguments
725
        != 0) {
726
        throw PyException(/*"Error running InterpreterSingleton::RunMethodVoid()"*/);
727
    }
728
}
729

730
PyObject* InterpreterSingleton::runMethodObject(PyObject* pobject, const char* method)
731
{
732
    PyObject* pcO {};
733

734
    PyGILStateLocker locker;
735
    if (PP_Run_Method(pobject,  // object
736
                      method,   // run method
737
                      "O",      // return type
738
                      &pcO,     // return object
739
                      "()")     // no arguments
740
        != 0) {
741
        throw PyException();
742
    }
743

744
    return pcO;
745
}
746

747
void InterpreterSingleton::runMethod(PyObject* pobject,
748
                                     const char* method,
749
                                     const char* resfmt,
750
                                     void* cresult, /* convert to c/c++ */
751
                                     const char* argfmt,
752
                                     ...) /* convert to python */
753
{
754
    PyObject* pmeth {};
755
    PyObject* pargs {};
756
    PyObject* presult {};
757
    va_list argslist; /* "pobject.method(args)" */
758
    va_start(argslist, argfmt);
759

760
    PyGILStateLocker locker;
761
    pmeth = PyObject_GetAttrString(pobject, method);
762
    if (!pmeth) { /* get callable object */
763
        va_end(argslist);
764
        throw AttributeError(
765
            "Error running InterpreterSingleton::RunMethod() method not defined"); /* bound method?
766
                                                                                      has self */
767
    }
768

769
    pargs = Py_VaBuildValue(argfmt, argslist); /* args: c->python */
770
    va_end(argslist);
771

772
    if (!pargs) {
773
        Py_DECREF(pmeth);
774
        throw TypeError("InterpreterSingleton::RunMethod() wrong arguments");
775
    }
776

777
#if PY_VERSION_HEX < 0x03090000
778
    presult = PyEval_CallObject(pmeth, pargs); /* run interpreter */
779
#else
780
    presult = PyObject_CallObject(pmeth, pargs); /* run interpreter */
781
#endif
782

783
    Py_DECREF(pmeth);
784
    Py_DECREF(pargs);
785
    if (PP_Convert_Result(presult, resfmt, cresult) != 0) {
786
        if (PyErr_Occurred()) {
787
            PyErr_Print();
788
        }
789
        throw RuntimeError(
790
            "Error running InterpreterSingleton::RunMethod() exception in called method");
791
    }
792
}
793

794
PyObject* InterpreterSingleton::getValue(const char* key, const char* result_var)
795
{
796
    PyObject* module {};
797
    PyObject* dict {};
798
    PyObject* presult {};
799

800
    PyGILStateLocker locker;
801
    module = PP_Load_Module("__main__"); /* get module, init python */
802
    if (!module) {
803
        throw PyException(); /* not incref'd */
804
    }
805
    dict = PyModule_GetDict(module); /* get dict namespace */
806
    if (!dict) {
807
        throw PyException(); /* not incref'd */
808
    }
809

810

811
    presult = PyRun_String(key, Py_file_input, dict, dict); /* eval direct */
812
    if (!presult) {
813
        throw PyException();
814
    }
815
    Py_DECREF(presult);
816

817
    return PyObject_GetAttrString(module, result_var);
818
}
819

820
void InterpreterSingleton::dbgObserveFile(const char* sFileName)
821
{
822
    if (sFileName) {
823
        _cDebugFileName = sFileName;
824
    }
825
    else {
826
        _cDebugFileName = "";
827
    }
828
}
829

830
void InterpreterSingleton::dbgSetBreakPoint(unsigned int /*uiLineNumber*/)
831
{}
832

833
void InterpreterSingleton::dbgUnsetBreakPoint(unsigned int /*uiLineNumber*/)
834
{}
835

836
void InterpreterSingleton::dbgStep()
837
{}
838

839
std::string InterpreterSingleton::strToPython(const char* Str)
840
{
841
    std::string result;
842
    const char* It = Str;
843

844
    while (*It != '\0') {
845
        switch (*It) {
846
            case '\\':
847
                result += "\\\\";
848
                break;
849
            case '\"':
850
                result += "\\\"";
851
                break;
852
            case '\'':
853
                result += "\\\'";
854
                break;
855
            default:
856
                result += *It;
857
        }
858
        It++;
859
    }
860

861
    return result;
862
}
863

864
// --------------------------------------------------------------------
865

866
int getSWIGVersionFromModule(const std::string& module)
867
{
868
    static std::map<std::string, int> moduleMap;
869
    std::map<std::string, int>::iterator it = moduleMap.find(module);
870
    if (it != moduleMap.end()) {
871
        return it->second;
872
    }
873
    try {
874
        // Get the module and check its __file__ attribute
875
        Py::Dict dict(PyImport_GetModuleDict());
876
        if (!dict.hasKey(module)) {
877
            return 0;
878
        }
879
        Py::Module mod(module);
880
        Py::String file(mod.getAttr("__file__"));
881
        std::string filename = (std::string)file;
882
        // file can have the extension .py or .pyc
883
        filename = filename.substr(0, filename.rfind('.'));
884
        filename += ".py";
885
        boost::regex rx("^# Version ([1-9])\\.([0-9])\\.([0-9]+)");
886
        boost::cmatch what;
887

888
        std::string line;
889
        Base::FileInfo fi(filename);
890

891
        Base::ifstream str(fi, std::ios::in);
892
        while (str && std::getline(str, line)) {
893
            if (boost::regex_match(line.c_str(), what, rx)) {
894
                int major = std::atoi(what[1].first);
895
                int minor = std::atoi(what[2].first);
896
                int micro = std::atoi(what[3].first);
897
                int version = (major << 16) + (minor << 8) + micro;
898
                moduleMap[module] = version;
899
                return version;
900
            }
901
        }
902
    }
903
    catch (Py::Exception& e) {
904
        e.clear();
905
    }
906

907
#if (defined(HAVE_SWIG) && (HAVE_SWIG == 1))
908
    moduleMap[module] = 0;
909
#endif
910
    return 0;
911
}
912

913
#if (defined(HAVE_SWIG) && (HAVE_SWIG == 1))
914
namespace Swig_python
915
{
916
extern int createSWIGPointerObj_T(const char* TypeName, void* obj, PyObject** ptr, int own);
917
extern int convertSWIGPointerObj_T(const char* TypeName, PyObject* obj, void** ptr, int flags);
918
extern void cleanupSWIG_T(const char* TypeName);
919
extern int getSWIGPointerTypeObj_T(const char* TypeName, PyTypeObject** ptr);
920
}  // namespace Swig_python
921
#endif
922

923
PyObject* InterpreterSingleton::createSWIGPointerObj(const char* Module,
924
                                                     const char* TypeName,
925
                                                     void* Pointer,
926
                                                     int own)
927
{
928
    int result = 0;
929
    PyObject* proxy = nullptr;
930
    PyGILStateLocker locker;
931
    (void)Module;
932
#if (defined(HAVE_SWIG) && (HAVE_SWIG == 1))
933
    result = Swig_python::createSWIGPointerObj_T(TypeName, Pointer, &proxy, own);
934
#else
935
    (void)TypeName;
936
    (void)Pointer;
937
    (void)own;
938
    result = -1;  // indicates error
939
#endif
940

941
    if (result == 0) {
942
        return proxy;
943
    }
944

945
    // none of the SWIG's succeeded
946
    throw Base::RuntimeError("No SWIG wrapped library loaded");
947
}
948

949
bool InterpreterSingleton::convertSWIGPointerObj(const char* Module,
950
                                                 const char* TypeName,
951
                                                 PyObject* obj,
952
                                                 void** ptr,
953
                                                 int flags)
954
{
955
    int result = 0;
956
    PyGILStateLocker locker;
957
    (void)Module;
958
#if (defined(HAVE_SWIG) && (HAVE_SWIG == 1))
959
    result = Swig_python::convertSWIGPointerObj_T(TypeName, obj, ptr, flags);
960
#else
961
    (void)TypeName;
962
    (void)obj;
963
    (void)ptr;
964
    (void)flags;
965
    result = -1;  // indicates error
966
#endif
967

968
    if (result == 0) {
969
        return true;
970
    }
971

972
    // none of the SWIG's succeeded
973
    throw Base::RuntimeError("No SWIG wrapped library loaded");
974
}
975

976
void InterpreterSingleton::cleanupSWIG(const char* TypeName)
977
{
978
    PyGILStateLocker locker;
979
#if (defined(HAVE_SWIG) && (HAVE_SWIG == 1))
980
    Swig_python::cleanupSWIG_T(TypeName);
981
#else
982
    (void)TypeName;
983
#endif
984
}
985

986
PyTypeObject* InterpreterSingleton::getSWIGPointerTypeObj(const char* Module, const char* TypeName)
987
{
988
    int result = 0;
989
    PyTypeObject* proxy = nullptr;
990
    PyGILStateLocker locker;
991
    (void)Module;
992
#if (defined(HAVE_SWIG) && (HAVE_SWIG == 1))
993
    result = Swig_python::getSWIGPointerTypeObj_T(TypeName, &proxy);
994
#else
995
    (void)TypeName;
996
    result = -1;  // indicates error
997
#endif
998

999
    if (result == 0) {
1000
        return proxy;
1001
    }
1002

1003
    // none of the SWIG's succeeded
1004
    throw Base::RuntimeError("No SWIG wrapped library loaded");
1005
}
1006

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.