2016-12-26 139 views
1

我試圖從類實例化C++中使用python-clang,即提取模板參數。 Python的綁定爲libclang(與clang 3.9)。例如,對於python-clang:獲取模板參數

template <typename T> class X {}; 
X<bool> x; 

我希望能夠弄清楚,X實例化一個bool作爲模板參數。

首先,它似乎有些功能,如get_num_template_arguments,不通過python-clang擺在首位,這是在cymbal似乎開始發揮作用,以猴補丁python-clang曝光。

有了這個,我能夠遠遠地得到這樣的:

#!/usr/bin/env python 

import clang.cindex 

clang.cindex.Config.set_library_file('/usr/lib/x86_64-linux-gnu/libclang-3.9.so.1') 

index = clang.cindex.Index.create() 

source = """ 
template <typename T> class X {}; 
X<bool> x; 
""" 

######### stolen from cymbal 

from ctypes import c_uint, c_int 

def find_libclang_function(function): 
    return getattr(clang.cindex.conf.lib, function) 

def monkeypatch_helper(classtype, name, library_function, args, result): 
    if hasattr(classtype, name): 
     raise ('failed to add method, %s is already available' % name) 
    f = find_libclang_function(library_function) 
    f.argtypes = args 
    f.restype = result 
    def impl(*args): 
     return f(*args) 
    setattr(classtype, name, impl) 

def monkeypatch_type(method_name, library_function, args, result): 
    monkeypatch_helper(clang.cindex.Type, method_name, library_function, args, result) 



monkeypatch_type('get_template_argument_type', 
         'clang_Type_getTemplateArgumentAsType', 
         [clang.cindex.Type, c_uint], 
         clang.cindex.Type) 

monkeypatch_type('get_num_template_arguments', 
         'clang_Type_getNumTemplateArguments', 
         [clang.cindex.Type], 
         c_int) 
######### /stolen from cymbal 

# helpers for visiting the AST recursively 
def visit(node, func): 
    func(node) 
    for c in node.get_children(): 
     visit(c, func) 

def visit_depth(node, func, depth=0): 
    func(node, depth) 
    for c in node.get_children(): 
     visit_depth(c, func, depth+1) 

# parse the TU 
tu = clang.cindex.TranslationUnit.from_source('t.cpp', ['-std=c++11'], unsaved_files=[('t.cpp', source)]) 

# show the AST 
def astprinter(node, depth): 
    print " "*depth, node.kind, node.spelling 
visit_depth(tu.cursor, astprinter)  

# find everything with a template and try to extract the template argument 
def template_finder(node): 
    if hasattr(node, 'type') and node.type.get_num_template_arguments() != -1: 
     print node.type.get_num_template_arguments(), node.spelling, node.kind, node.get_template_argument_type(0).kind 
visit(tu.cursor, template_finder) 

此輸出:

CursorKind.TRANSLATION_UNIT t.cpp 
    CursorKind.CLASS_TEMPLATE X 
    CursorKind.TEMPLATE_TYPE_PARAMETER T 
    CursorKind.VAR_DECL x 
    CursorKind.TEMPLATE_REF X 
    CursorKind.CALL_EXPR X 
1 x CursorKind.VAR_DECL TypeKind.INVALID 
1 X CursorKind.CALL_EXPR TypeKind.INVALID 

我期待node.get_template_argument_type(0).kindtemplate_finder返回的東西,帶給我bool,但我找不到任何東西。這是正確的路嗎?是否有可能獲得當前狀態python-clang的模板參數?

+0

只是一個關於cy的澄清 - 這是一個很大的阻止差距,是爲了防止任何人不得不復制和粘貼代碼注入使用ctypes功能。 自從它發佈以來,出現了一些重要的重構(例如/ clang.cindex> = 3.9,現在有一個register_function),這使得它不重要。 –

+0

關於cymbal的許可 - 它是根據MIT許可發佈的,所以如果您做出適當的歸屬,重用/回收您喜歡的任何代碼就可以了。 –

回答

1

我認爲,所有你真的缺少的是一對夫婦的模板取景的地方.type,但作爲參考,這對我的作品,甚至在鐺一樣古老3.7

import clang.cindex 
from clang.cindex import * 
import cymbal 
from ctypes import * 

cymbal.monkeypatch_type('get_template_argument_type', 
         'clang_Type_getTemplateArgumentAsType', 
         [Type, c_uint], 
         Type) 

cymbal.monkeypatch_type('get_num_template_arguments', 
         'clang_Type_getNumTemplateArguments', 
         [Type], 
         c_int) 


# check if the cursor's type is a template 
def is_template(node): 
    return hasattr(node, 'type') and node.type.get_num_template_arguments() != -1 

index = clang.cindex.Index.create() 

source = """ 
template <typename T> class X {}; 
X<bool> x; 
""" 
# parse the TU 
tu = clang.cindex.TranslationUnit.from_source('t.cpp', ['-std=c++11'], unsaved_files=[('t.cpp', source)]) 

for c in tu.cursor.walk_preorder(): 
    if is_template(c): 
     t = c.type 
     print t.kind, t.spelling, t.get_num_template_arguments() 
     print t.get_template_argument_type(0).spelling 

其中給出:

TypeKind.UNEXPOSED X<bool> 1 
bool 
TypeKind.UNEXPOSED X<bool> 1 
bool 
+0

完美工作,謝謝 - 同樣對於關於cy的澄清,我會看看進入那個。 – rainer