MeshLib Documentation
Loading...
Searching...
No Matches
MREmbeddedPython.h
Go to the documentation of this file.
1#pragma once
2
3#include "exports.h"
4
5#include <atomic>
6#include <condition_variable>
7#include <filesystem>
8#include <functional>
9#include <mutex>
10#include <string>
11#include <thread>
12#include <vector>
13
14namespace MR
15{
16
17class MRPYTHON_CLASS EmbeddedPython
18{
19public:
20 struct Config
21 {
22 bool siteImport{ true };
23 std::string home;
24 std::vector<std::string> argv;
25 };
26 MRPYTHON_API static Config pythonConfig; // Set this once before running anything.
27
28 static MRPYTHON_API bool isAvailable();
29
30 // Returns true if the interpreter is busy running something.
31 // If you try to run something else, your thread will block until it's done.
32 [[nodiscard]] static bool nowRunning() { return instance_().state_.load() != State::idle; }
33
34 // Returns false on failure.
35 // If `onDoneAsync` is set, doesn't wait for the script to finish.
36 // Will call `onDoneAsync` asynchronously when done (from the Python interpreter thread).
37 static MRPYTHON_API bool runString( std::string pythonString, std::function<void( bool success )> onDoneAsync = nullptr );
38
39 static MRPYTHON_API bool runScript( const std::filesystem::path& path );
40
41 static MRPYTHON_API bool isPythonScript( const std::filesystem::path& path );
42private:
44 EmbeddedPython( const EmbeddedPython& ) = delete;
45 EmbeddedPython& operator=( const EmbeddedPython& ) = delete;
47
48 bool init_();
49 void ensureInterpreterThreadIsRunning_();
50
51 MRPYTHON_API static EmbeddedPython& instance_();
52 bool available_{ false };
53
54 enum class State
55 {
56 idle, // Waiting for a script to run.
57 running, // Interpreter is running.
58 finishing, // Interpreter is done, waiting for the submitter thread to read the result.
59 };
60
61 std::atomic<State> state_ = State::idle; // Making this atomic allows `nowRunning()` to read this without locking the mutex.
62 std::string queuedSource_;
63 bool lastRunSuccessful_ = false;
64 std::function<void( bool success )> onDoneAsync_;
65 std::mutex cvMutex_;
66 std::condition_variable cv_; // It's could (?) be more efficient to have more CVs here, but one is simpler.
67
68 // We maintain ONE persistent thread that runs all python scripts, and persists while the program runs.
69 // This seems to be the safest option, I had issues otherwise. We need everything Python-related to happen in the same thread,
70 // and we also need to not finalize-and-recreate the interpreter while the program runs because that breaks our generated bindings
71 // (which may or may not be possible to fix in the bindings, but it's easier not to, and the manual even advises that
72 // some modules can break if you recreate the interpeter: https://docs.python.org/3/c-api/init.html#c.Py_FinalizeEx).
73
74 std::thread interpreterThread_;
75
76 std::atomic_bool stopInterpreterThread_ = false;
77};
78
79} //namespace MR
Definition MREmbeddedPython.h:18
static MRPYTHON_API bool isAvailable()
static MRPYTHON_API bool runScript(const std::filesystem::path &path)
static MRPYTHON_API bool isPythonScript(const std::filesystem::path &path)
static bool nowRunning()
Definition MREmbeddedPython.h:32
static MRPYTHON_API bool runString(std::string pythonString, std::function< void(bool success)> onDoneAsync=nullptr)
static MRPYTHON_API Config pythonConfig
Definition MREmbeddedPython.h:26
Definition MRCameraOrientationPlugin.h:8
Definition MREmbeddedPython.h:21
std::string home
Definition MREmbeddedPython.h:23
std::vector< std::string > argv
Definition MREmbeddedPython.h:24