mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +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
|
||||
#include <Python.h>
|
||||
#include <frameobject.h>
|
||||
#ifdef isalnum
|
||||
#undef isalnum
|
||||
#undef isalpha
|
||||
@ -122,6 +123,8 @@ struct cast_error : public std::runtime_error { public: cast_error(const
|
||||
|
||||
NAMESPACE_BEGIN(detail)
|
||||
|
||||
inline std::string error_string();
|
||||
|
||||
/// PyObject wrapper around generic types
|
||||
template <typename type, typename holder_type = std::unique_ptr<type>> struct instance {
|
||||
PyObject_HEAD
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
void inc_ref() const { Py_XINCREF(m_ptr); }
|
||||
void dec_ref() const { Py_XDECREF(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[](const char *key);
|
||||
inline detail::accessor attr(handle key);
|
||||
@ -325,6 +326,17 @@ public:
|
||||
class function : public object {
|
||||
public:
|
||||
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 {
|
||||
@ -365,5 +377,30 @@ inline internals &get_internals() {
|
||||
}
|
||||
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(pybind)
|
||||
|
Loading…
Reference in New Issue
Block a user