Exteor/include/xtr/core/PyCore.h

116 lines
3.2 KiB
C
Raw Permalink Normal View History

2024-06-07 20:30:06 +03:00
#pragma once
#include <string>
#include <map>
// Note: forward declare basic object class for Python
struct _object; // NOLINT(bugprone-reserved-identifier, cert-dcl37-c, cert-dcl51-cpp)
namespace cxxpython {
//! PyObject wrapper
/*!
Uses Python ref counting
*/
class Object {
_object* object;
public:
~Object() noexcept;
Object(const Object& obj2) noexcept;
Object& operator=(const Object& obj2) noexcept;
Object(Object&& obj2) noexcept;
Object& operator=(Object&& obj2) noexcept;
private:
explicit Object(_object* objectIn) noexcept
: object{ objectIn } {}
public:
explicit(false) Object(nullptr_t) noexcept // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
: object{ nullptr } {}
[[nodiscard]] static Object FromNew(_object* objectIn) noexcept;
[[nodiscard]] static Object FromBorrowed(_object* objectIn) noexcept;
public:
[[nodiscard]] Object at(int index) const noexcept;
[[nodiscard]] constexpr bool operator!=(nullptr_t) const noexcept { return object != nullptr; }
[[nodiscard]] constexpr bool operator==(nullptr_t) const noexcept { return object == nullptr; }
// Note: use with Python/C API only!
[[nodiscard]] constexpr _object* get() noexcept { return object; }
[[nodiscard]] constexpr _object* get() const noexcept { return object; }
private:
void DecreaseRefCount() noexcept;
};
//! Convert object to string
std::string ToString(const Object& object);
//! Convert object to long
long ToLong(const Object& object) noexcept;
//! Convert object to bool
bool ToBool(const Object& object) noexcept;
//! Python callable wrapper
class Callable {
Object func;
public:
explicit(false) Callable(nullptr_t) noexcept // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
: func{ nullptr } {}
explicit Callable(_object* object) noexcept;
public:
constexpr bool operator!=(nullptr_t) const noexcept { return func != nullptr; }
constexpr bool operator==(nullptr_t) const noexcept { return func == nullptr; }
Object operator()() const noexcept;
Object operator()(const char* format, ...) const noexcept;
};
//! Python interpreter wrapper
class PyCore {
struct Module {
Object pyModule{ nullptr };
Object pyDictionary{ nullptr };
};
bool isRunning{ false };
std::map<std::string, Module> modules{};
public:
PyCore(const PyCore&) = delete;
PyCore& operator=(const PyCore&) = delete;
private:
~PyCore();
PyCore() = default;
public:
static PyCore& Instance();
public:
//! Start Python interpreter from local path.
/*!
Requires: The argument should point to a zero-terminated character string
in static storage whose contents will not change
for the duration of the programs execution
see https://docs.python.org/3/c-api/init.html#c.Py_SetPythonHome
*/
bool Start(const wchar_t* pyPath = nullptr) noexcept;
//! Stop Python interpreter.
/*!
Requires: Every Object should be destroyed before calling PyCore.Stop()
*/
void Stop() noexcept;
[[nodiscard]] bool IsRunning() const noexcept;
bool LoadModule(const std::string& moduleName, const std::string& pyFileName);
[[nodiscard]] Callable PyFunction(const std::string& moduleName, const std::string& funcName) const;
};
} // namespace cxxpython