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
diff --git a/include/pybind/common.h b/include/pybind/common.h
index d327ab6..3a95210 100644
--- a/include/pybind/common.h
+++ b/include/pybind/common.h
@@ -41,6 +41,7 @@
 #endif
 #endif
 #include <Python.h>
+#include <frameobject.h>
 #ifdef isalnum
 #undef isalnum
 #undef isalpha
@@ -122,6 +123,8 @@
 
 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
diff --git a/include/pybind/pytypes.h b/include/pybind/pytypes.h
index e9a60e9..4559ffb 100644
--- a/include/pybind/pytypes.h
+++ b/include/pybind/pytypes.h
@@ -32,6 +32,7 @@
     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 @@
 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 @@
     }
     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)