mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
A few convenience functions for working with Python types
- Get a descriptive string after a Python exception (without changing the exception status) - Convenience function to map from a C++ object to a Python handle - Convenience to check if a pybind::function is defined by an underlying C++ implementation - Get the type object of a pybind::handle
This commit is contained in:
parent
5257330e6a
commit
96c10530aa
@ -41,6 +41,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
#include <frameobject.h>
|
||||||
#ifdef isalnum
|
#ifdef isalnum
|
||||||
#undef isalnum
|
#undef isalnum
|
||||||
#undef isalpha
|
#undef isalpha
|
||||||
@ -122,6 +123,8 @@ struct cast_error : public std::runtime_error { public: cast_error(const
|
|||||||
|
|
||||||
NAMESPACE_BEGIN(detail)
|
NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
inline std::string error_string();
|
||||||
|
|
||||||
/// PyObject wrapper around generic types
|
/// PyObject wrapper around generic types
|
||||||
template <typename type, typename holder_type = std::unique_ptr<type>> struct instance {
|
template <typename type, typename holder_type = std::unique_ptr<type>> struct instance {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
@ -32,6 +32,7 @@ public:
|
|||||||
void inc_ref() const { Py_XINCREF(m_ptr); }
|
void inc_ref() const { Py_XINCREF(m_ptr); }
|
||||||
void dec_ref() const { Py_XDECREF(m_ptr); }
|
void dec_ref() const { Py_XDECREF(m_ptr); }
|
||||||
int ref_count() const { return (int) Py_REFCNT(m_ptr); }
|
int ref_count() const { return (int) Py_REFCNT(m_ptr); }
|
||||||
|
handle get_type() { return (PyObject *) Py_TYPE(m_ptr); }
|
||||||
inline detail::accessor operator[](handle key);
|
inline detail::accessor operator[](handle key);
|
||||||
inline detail::accessor operator[](const char *key);
|
inline detail::accessor operator[](const char *key);
|
||||||
inline detail::accessor attr(handle key);
|
inline detail::accessor attr(handle key);
|
||||||
@ -325,6 +326,17 @@ public:
|
|||||||
class function : public object {
|
class function : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND_OBJECT_DEFAULT(function, object, PyFunction_Check)
|
PYBIND_OBJECT_DEFAULT(function, object, PyFunction_Check)
|
||||||
|
|
||||||
|
bool is_cpp_function() {
|
||||||
|
PyObject *ptr = m_ptr;
|
||||||
|
if (ptr == nullptr)
|
||||||
|
return false;
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
if (PyMethod_Check(ptr))
|
||||||
|
ptr = PyMethod_GET_FUNCTION(ptr);
|
||||||
|
#endif
|
||||||
|
return PyCFunction_Check(ptr);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class buffer : public object {
|
class buffer : public object {
|
||||||
@ -365,5 +377,30 @@ inline internals &get_internals() {
|
|||||||
}
|
}
|
||||||
return *internals_ptr;
|
return *internals_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string error_string() {
|
||||||
|
std::string errorString;
|
||||||
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
|
if (tstate == nullptr)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
if (tstate->curexc_type) {
|
||||||
|
errorString += (const char *) handle(tstate->curexc_type).str();
|
||||||
|
errorString += ": ";
|
||||||
|
}
|
||||||
|
if (tstate->curexc_value)
|
||||||
|
errorString += (const char *) handle(tstate->curexc_value).str();
|
||||||
|
|
||||||
|
return errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline handle get_object_handle(const void *ptr) {
|
||||||
|
auto instances = get_internals().registered_instances;
|
||||||
|
auto it = instances.find(ptr);
|
||||||
|
if (it == instances.end())
|
||||||
|
throw std::runtime_error("Internal error: could not acquire Python handle of a C++ object");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
NAMESPACE_END(detail)
|
NAMESPACE_END(detail)
|
||||||
NAMESPACE_END(pybind)
|
NAMESPACE_END(pybind)
|
||||||
|
Loading…
Reference in New Issue
Block a user