116 lines
3.2 KiB
C++
116 lines
3.2 KiB
C++
#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 program’s 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
|