Clang 如何以字符串的形式获取函数定义/签名?
假设我有一个CXCursor左右,如何使用Clang/Libclang将函数的签名(或至少整个定义?)作为字符串获取Clang 如何以字符串的形式获取函数定义/签名?,clang,libclang,Clang,Libclang,假设我有一个CXCursor左右,如何使用Clang/Libclang将函数的签名(或至少整个定义?)作为字符串获取 我认为可以通过使用游标的区段以某种方式获得定义,但我真的不知道如何(使用什么函数)。您可以使用此简单代码获得函数原型(名称、返回类型、参数计数和参数[名称、数据类型]) 字符串转换(常量CXString&s) { 字符串结果=clang_getCString(s); 叮当作响的处置; 返回结果; } 无效打印功能原型(CXCursor) { //TODO:打印数据! 自动类型=c
我认为可以通过使用游标的区段以某种方式获得定义,但我真的不知道如何(使用什么函数)。您可以使用此简单代码获得函数原型(名称、返回类型、参数计数和参数[名称、数据类型])
字符串转换(常量CXString&s)
{
字符串结果=clang_getCString(s);
叮当作响的处置;
返回结果;
}
无效打印功能原型(CXCursor)
{
//TODO:打印数据!
自动类型=clang_getCursorType(光标);
自动函数_name=Convert(clang_getCursorSpelling(游标));
自动返回类型=转换(clanggettypespelling(clanggetresulttype(type));
int num_args=clang_Cursor_getNumArguments(Cursor);
对于(int i=0;i
您可以尝试使用clang\u Cursor\u getMangling()
并对结果进行demangle处理,以获得完整的定义。我将以下内容用于我正在进行的一个项目,它对定义非常有用。TL&DR clang_getCursorPrettyPrinted,策略TerseOutput设置为true
std::string getStdString(const CXString &s)
{
std::string rv = clang_getCString(s);
clang_disposeString(s);
return rv;
}
bool isFunctionImplementation(CXCursor &cursor,std::string &decl,std::string &filename,unsigned &lineno)
{
std::string cs = getStdString(clang_getCursorPrettyPrinted(cursor,nullptr));
if (cs.find('{') == std::string::npos) // Just a declaration, not the "meat" of the function, so we dont care
return false;
clang::LangOptions lo;
struct clang::PrintingPolicy pol(lo);
pol.adjustForCPlusPlus();
pol.TerseOutput = true;
pol.FullyQualifiedName = true;
decl = getStdString(clang_getCursorPrettyPrinted(cursor,&pol));
CXSourceLocation location = clang_getCursorLocation( cursor );
CXFile f;
lineno = 0;
filename = "(None)";
clang_getSpellingLocation(location,&f,&lineno,nullptr,nullptr);
if (lineno)
{
filename = getStdString(clang_File_tryGetRealPathName(f));
}
return isAllowedDirectory(filename);
}
这个函数检查函数调用是“meat”还是仅仅是一个定义。显然,您可以根据需要进行调整,包括编写自己的isAllowedDirectory函数。当您点击声明类型时,只需在AST中传递光标、两个字符串和一个未签名的字符即可。我使用以下简短的方法处理clang 10(尽管它使用的是匹配器,而不是光标): 这两个helper函数是将代码段作为字符串获取的常规帮助程序
// helper function 1: find position of end of token
SourceLocation
end_of_the_end(SourceLocation const & start_of_end, SourceManager & sm)
{
using namespace clang;
LangOptions lopt;
return Lexer::getLocForEndOfToken(start_of_end, 0, sm, lopt);
}
// helper function 2:
std::string getSymbolString(clang::SourceManager & sm,
const clang::SourceRange & range)
{
return std::string(sm.getCharacterData(range.getBegin()),
sm.getCharacterData(end_of_the_end(range.getEnd(), sm)));
}
获取函数声明字符串的实际代码段为:
// ... in run() of a matcher:
virtual void run(corct::result_t const & result) override
{
using namespace clang;
FunctionDecl * f_decl = const_cast<FunctionDecl *>(
result.Nodes.getNodeAs<FunctionDecl>(fd_bd_name_));
if(f_decl) {
SourceManager & sm(result.Context->getSourceManager());
FunctionDecl * f_decl = const_cast<FunctionDecl *>(
result.Nodes.getNodeAs<FunctionDecl>(fd_bd_name_));
auto full_decl_string =
getSymbolString(sm, f_decl->DeclaratorDecl::getSourceRange());
}
}
/。。。在匹配器的run()中:
虚拟无效运行(corct::result\t const&result)覆盖
{
使用名称空间铿锵;
函数decl*f_decl=const_cast(
result.Nodes.getNodeAs(fd_bd_name);
如果(f_decl){
SourceManager&sm(result.Context->getSourceManager());
函数decl*f_decl=const_cast(
result.Nodes.getNodeAs(fd_bd_name);
自动满decl字符串=
getSymbolString(sm,f_decl->DeclaratorDecl::getSourceRange());
}
}
这将为以下函数输出内联bool test2(std::string const&str,std::vector&sss)
:
inline bool test2(std::string const & str, std::vector<std::string> & sss)
{
return true;
}
inline bool test2(std::string const&str,std::vector&sss)
{
返回true;
}
C不是像javaI那样的解释语言,我不明白你的意思,对不起。但是为什么解释Java?我在主帖中将“cursor”改为“CXCursor”,我指的是叮当作响的cursor。是的,但将其全部组合回函数签名似乎不是一件简单的工作(以函数指针为例)特别是考虑到它已经完成并且函数签名已经存在于源文件中。@Predelnik hmm你能给我一个例子吗[以函数指针为例]?我的意思是如果你有类似于void f(void(*arg)(int,int))
的东西,你可以提取arg
和void(*)(int,int)
但将它们组合回签名将需要计算出将arg
放在类型中的确切位置,这并不容易。@Predelnik是的,这个示例很难在libclang中提取arg,但我认为我们可以使用clang libtools来完成。请参阅此链接,非常感谢。很遗憾,我不再使用clang,但我希望如此如果我再次使用你的答案,你的答案将对其他人甚至我有用:)。
inline bool test2(std::string const & str, std::vector<std::string> & sss)
{
return true;
}