LibClang exposes a function to "determine the set of methods that are overridden by the given method" (explained here). However this function does not seem to be exposed in the python bindings. Could someone explain how to add this function to the bindings or did I just not find it?
1 Answers
In general, adding methods to libclang follows the same basic pattern used in the library itself.
- You use ctypes to find a handle to the method you want to wrap.
- You specify the extra type information about arguments and return types.
- You wrap that ctypes function in a python function that deals with any corner cases / caching.
For simple cases, you can use cymbal, a new Python module that came out of some experiments trying to answer this question. Cymbal lets you tack methods onto libclang types and cursors.
However, clang_getOverriddenCursors
is slightly more complex than normal because you need to dispose of the memory returned by calling clang_disposeOverriddenCursors
.
Additionally, libclang does some magic that means the cursors you get back from that function aren't valid for all function calls (they omit a pointer to the translation unit), So you also need to generate updated cursors (based on the translation unit and location).
Sample code:
import clang.cindex
from clang.cindex import *
clang_getOverriddenCursors = clang.cindex.conf.lib.clang_getOverriddenCursors
clang_getOverriddenCursors.restype = None
clang_getOverriddenCursors.argtypes = [Cursor, POINTER(POINTER(Cursor)), POINTER(c_uint)]
clang_disposeOverriddenCursors = clang.cindex.conf.lib.clang_disposeOverriddenCursors
clang_disposeOverriddenCursors.restype = None
clang_disposeOverriddenCursors.argtypes = [ POINTER(Cursor) ]
def get_overriden_cursors(self):
cursors = POINTER(Cursor)()
num = c_uint()
clang_getOverriddenCursors(self, byref(cursors), byref(num))
updcursors = []
for i in xrange(int(num.value)):
c = cursors[i]
updcursor = Cursor.from_location(self._tu, c.location)
updcursors.append( updcursor )
clang_disposeOverriddenCursors(cursors)
return updcursors
Assuming that you want to parse something like this:
// sample.cpp
class foo {
public:
virtual void f();
};
class bar : public foo {
public:
virtual void f();
};
You can find methods in the tree
idx = Index.create()
tu = idx.parse('sample.cpp', args = '-x c++'.split())
methods = []
for c in tu.cursor.walk_preorder():
if c.kind == CursorKind.CXX_METHOD:
methods.append(c)
You can then see the overrides
def show_method(method):
return method.semantic_parent.spelling + '::' + method.spelling
for m in methods:
for override in get_overriden_cursors(m):
print show_method(m), 'overrides', show_method(override)
Which for me prints:
bar::f overrides foo::f

- 40,984
- 8
- 62
- 84