aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2024-04-18 16:07:52 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-04-22 18:58:26 +0000
commit6c02ef8fc04b76ec3a4fb13e3f24f4fc30fb4c86 (patch)
tree2857b4f963cbc5ba235d808b79de8841fe99fa52
parenta85e7f01864ddc77e095ac3eeb668c530db00aad (diff)
shibokenmodule: Expose dumpTypeGraph(), dumpWrapperMap() from the binding manager
This is helpful for gaining some insight into the instantiated wrappers and registered types. Move the existing graph generating code out of the graph class and format the nodes with a short name and tooltip and expose it as dumpTypeGraph(). Similarly, rewrite expose showWrapperMap() to use streams and expose it as dumpWrapperMap(). Change-Id: I5cff442b7285388403dcf1c9f96fa8808c7b2d05 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> (cherry picked from commit 193769216f60f87feb20bbffa832cc159bbe525c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/shiboken6/doc/shibokenmodule.rst9
-rw-r--r--sources/shiboken6/libshiboken/bindingmanager.cpp107
-rw-r--r--sources/shiboken6/libshiboken/bindingmanager.h3
-rw-r--r--sources/shiboken6/shibokenmodule/shibokenmodule.cpp9
-rw-r--r--sources/shiboken6/shibokenmodule/typesystem_shiboken.xml8
5 files changed, 102 insertions, 34 deletions
diff --git a/sources/shiboken6/doc/shibokenmodule.rst b/sources/shiboken6/doc/shibokenmodule.rst
index b31efbcd1..2f1c6d166 100644
--- a/sources/shiboken6/doc/shibokenmodule.rst
+++ b/sources/shiboken6/doc/shibokenmodule.rst
@@ -116,6 +116,15 @@ To import the module:
This method should be used **only** for debug purposes by developers.
+ .. function:: dumpTypeGraph(file_name)
+
+ Dumps the inheritance graph of the types existing in libshiboken
+ to ``.dot`` file for use with `Graphviz <https://graphviz.org/>`_.
+
+.. function:: dumpWrapperMap()
+
+ Dumps the map of wrappers existing in libshiboken to standard error.
+
.. py:class:: VoidPtr(address, size = -1, writeable = 0)
:param address: (PyBuffer, SbkObject, int, VoidPtr)
diff --git a/sources/shiboken6/libshiboken/bindingmanager.cpp b/sources/shiboken6/libshiboken/bindingmanager.cpp
index a0acc4e4b..7542e60b8 100644
--- a/sources/shiboken6/libshiboken/bindingmanager.cpp
+++ b/sources/shiboken6/libshiboken/bindingmanager.cpp
@@ -15,8 +15,11 @@
#include <cstddef>
#include <cstring>
#include <fstream>
+#include <iostream>
#include <mutex>
+#include <string_view>
#include <unordered_map>
+#include <unordered_set>
namespace Shiboken
{
@@ -27,6 +30,8 @@ class Graph
{
public:
using NodeList = std::vector<PyTypeObject *>;
+ using NodeSet = std::unordered_set<const PyTypeObject *>;
+
using Edges = std::unordered_map<PyTypeObject *, NodeList>;
Edges m_edges;
@@ -38,25 +43,8 @@ public:
m_edges[from].push_back(to);
}
-#ifndef NDEBUG
- void dumpDotGraph() const
- {
- std::ofstream file("/tmp/shiboken_graph.dot");
-
- file << "digraph D {\n";
-
- for (const auto &p : m_edges) {
- auto *node1 = p.first;
- const NodeList &nodeList = p.second;
- for (const PyTypeObject *o : nodeList) {
- auto *node2 = o;
- file << '"' << node2->tp_name << "\" -> \""
- << node1->tp_name << "\"\n";
- }
- }
- file << "}\n";
- }
-#endif
+ bool dumpTypeGraph(const char *fileName) const;
+ NodeSet nodeSet() const;
PyTypeObject *identifyType(void **cptr, PyTypeObject *type, PyTypeObject *baseType) const
{
@@ -85,24 +73,53 @@ public:
}
};
+static void formatDotNode(const char *nameC, std::ostream &file)
+{
+ std::string_view name(nameC);
+ auto lastDot = name.rfind('.');
+ file << " \"" << name << "\" [ label=";
+ if (lastDot != std::string::npos) {
+ file << '"' << name.substr(lastDot + 1) << "\" tooltip=\""
+ << name.substr(0, lastDot) << '"';
+ } else {
+ file << '"' << name << '"';
+ }
+ file << " ]\n";
+}
-#ifndef NDEBUG
-static void showWrapperMap(const WrapperMap &wrapperMap)
+Graph::NodeSet Graph::nodeSet() const
{
- if (Shiboken::pyVerbose() > 0) {
- fprintf(stderr, "-------------------------------\n");
- fprintf(stderr, "WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size());
- for (auto it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) {
- const SbkObject *sbkObj = it->second;
- fprintf(stderr, "key: %p, value: %p (%s, refcnt: %d)\n", it->first,
- static_cast<const void *>(sbkObj),
- (Py_TYPE(sbkObj))->tp_name,
- int(Py_REFCNT(reinterpret_cast<const PyObject *>(sbkObj))));
- }
- fprintf(stderr, "-------------------------------\n");
+ NodeSet result;
+ for (const auto &p : m_edges) {
+ result.insert(p.first);
+ for (const PyTypeObject *node2 : p.second)
+ result.insert(node2);
}
+ return result;
+}
+
+bool Graph::dumpTypeGraph(const char *fileName) const
+{
+ std::ofstream file(fileName);
+ if (!file.good())
+ return false;
+
+ file << "digraph D {\n";
+
+ // Define nodes with short names
+ for (const auto *node : nodeSet())
+ formatDotNode(node->tp_name, file);
+
+ // Write edges
+ for (const auto &p : m_edges) {
+ auto *node1 = p.first;
+ const NodeList &nodeList = p.second;
+ for (const PyTypeObject *node2 : nodeList)
+ file << " \"" << node2->tp_name << "\" -> \"" << node1->tp_name << "\"\n";
+ }
+ file << "}\n";
+ return true;
}
-#endif
struct BindingManager::BindingManagerPrivate {
using DestructorEntries = std::vector<DestructorEntry>;
@@ -189,7 +206,8 @@ BindingManager::~BindingManager()
debugRemoveFreeHook();
#endif
#ifndef NDEBUG
- showWrapperMap(m_d->wrapperMapper);
+ if (Shiboken::pyVerbose() > 0)
+ dumpWrapperMap();
#endif
/* Cleanup hanging references. We just invalidate them as when
* the BindingManager is being destroyed the interpreter is alredy
@@ -395,6 +413,27 @@ void BindingManager::visitAllPyObjects(ObjectVisitor visitor, void *data)
}
}
+bool BindingManager::dumpTypeGraph(const char *fileName) const
+{
+ return m_d->classHierarchy.dumpTypeGraph(fileName);
+}
+
+void BindingManager::dumpWrapperMap()
+{
+ const auto &wrapperMap = m_d->wrapperMapper;
+ std::cerr << "-------------------------------\n"
+ << "WrapperMap size: " << wrapperMap.size() << " Types: "
+ << m_d->classHierarchy.nodeSet().size() << '\n';
+ for (auto it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) {
+ const SbkObject *sbkObj = it->second;
+ std::cerr << "key: " << it->first << ", value: "
+ << static_cast<const void *>(sbkObj) << " ("
+ << (Py_TYPE(sbkObj))->tp_name << ", refcnt: "
+ << Py_REFCNT(reinterpret_cast<const PyObject *>(sbkObj)) << ")\n";
+ }
+ std::cerr << "-------------------------------\n";
+}
+
static bool isPythonType(PyTypeObject *type)
{
// This is a type which should be called by multiple inheritance.
diff --git a/sources/shiboken6/libshiboken/bindingmanager.h b/sources/shiboken6/libshiboken/bindingmanager.h
index 4b21ae835..47db14975 100644
--- a/sources/shiboken6/libshiboken/bindingmanager.h
+++ b/sources/shiboken6/libshiboken/bindingmanager.h
@@ -59,6 +59,9 @@ public:
*/
void visitAllPyObjects(ObjectVisitor visitor, void *data);
+ bool dumpTypeGraph(const char *fileName) const;
+ void dumpWrapperMap();
+
private:
~BindingManager();
BindingManager();
diff --git a/sources/shiboken6/shibokenmodule/shibokenmodule.cpp b/sources/shiboken6/shibokenmodule/shibokenmodule.cpp
index 6feca9ea8..b3adfe78b 100644
--- a/sources/shiboken6/shibokenmodule/shibokenmodule.cpp
+++ b/sources/shiboken6/shibokenmodule/shibokenmodule.cpp
@@ -91,6 +91,15 @@ for (auto *o : setAll) {
return listAll;
// @snippet getallvalidwrappers
+// @snippet dumptypegraph
+const bool ok = Shiboken::BindingManager::instance().dumpTypeGraph(%1);
+%PYARG_0 = %CONVERTTOPYTHON[bool](ok);
+// @snippet dumptypegraph
+
+// @snippet dumpwrappermap
+Shiboken::BindingManager::instance().dumpWrapperMap();
+// @snippet dumpwrappermap
+
// @snippet init
// Add __version__ and __version_info__ attributes to the module
PyObject* version = PyTuple_New(5);
diff --git a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
index 2288ca7a4..aa08a8bbf 100644
--- a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
+++ b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
@@ -49,6 +49,14 @@
<inject-code file="shibokenmodule.cpp" snippet="getallvalidwrappers"/>
</add-function>
+ <add-function signature="dumpTypeGraph(const char *@fileName@)" return-type="bool">
+ <inject-code file="shibokenmodule.cpp" snippet="dumptypegraph"/>
+ </add-function>
+
+ <add-function signature="dumpWrapperMap()">
+ <inject-code file="shibokenmodule.cpp" snippet="dumpwrappermap"/>
+ </add-function>
+
<extra-includes>
<include file-name="sbkversion.h" location="local"/>
<include file-name="voidptr.h" location="local"/>