如何使用C API而不是实际知道使用Clang编写的var类型?

时间:2013-11-11 12:09:55

标签: c++ c clang

我正在尝试通过C API使用Clang,索引要详细。问题是某些类型不是在编写时返回,而是在编译时返回。例如“Stream&”成为“int&”并且“byte”变为“int。

一些测试库:

// TODO make it a subclass of a generic Serial/Stream base class
class FirmataClass
{
public:
    FirmataClass(Stream &s);

    void setFirmwareNameAndVersion(const char *name, byte major, byte minor);

我正在使用代码获取方法信息:

void showMethodInfo(const CXIdxDeclInfo *info) {
    int numArgs = clang_Cursor_getNumArguments(info->cursor);
    fprintf(stderr, "  %i args:\n", numArgs);

    for (int i=0; i<numArgs; i++) {
        CXCursor argCursor = clang_Cursor_getArgument(info->cursor, i);
        CXString name = clang_getCursorDisplayName(argCursor);
        CXString spelling = clang_getCursorSpelling(argCursor);

        CXType type = clang_getCursorType(argCursor);
        CXString typeSpelling = clang_getTypeSpelling(type);

        CXCursorKind kind = clang_getCursorKind(argCursor);

        fprintf(stderr, "  kind=[%s (%i)], type=[%s], spelling=[%s]\n",
            cursor_kinds[kind], kind, clang_getCString(typeSpelling),
            clang_getCString(spelling));

        clang_disposeString(name);
        clang_disposeString(spelling);
        clang_disposeString(typeSpelling);
    }

    // return type
    CXType returnType = clang_getCursorResultType(info->cursor);
    CXString returnTypeSpelling = clang_getTypeSpelling(returnType);

    fprintf(stderr, " returns %s\n", clang_getCString(returnTypeSpelling));
    clang_disposeString(returnTypeSpelling);
}

输出:

  

[105:10 4689] access = [CX_CXXPublic]   kind = [CXIdxEntity_CXXInstanceMethod](21)   name = [setFirmwareNameAndVersion] is_container = [0] 3 args:
  kind = [CXCursor_ParmDecl(10)],type = [const char *],spelling = [name]
  kind = [CXCursor_ParmDecl(10)],type = [int],spelling = [major]
  kind = [CXCursor_ParmDecl(10)],type = [int],拼写= [minor]   返回无效

因此,您可以看到byte函数参数被描述为int。 我怎样才能获得实际的拼写?

3 个答案:

答案 0 :(得分:2)

通过typedef或#define?

声明byte

当我声明这些类型时:

typedef int MyType_t;
#define MyType2_t int

class Foo
{
public:
    bool bar( MyType_t a, MyType2_t b );
};

然后打印我从clang_GetTypeSpelling得到的类型名称这就是我得到的:

bool Foo_bar(  MyType_t a, int b )

Libclang可能无法打印#defined名称,因为预处理器在构建解析树时已经用int替换了它。

答案 1 :(得分:2)

几天前我已经解决了这个问题。

"Stream &" becomes "int &" and "byte" becomes "int.

libclang不知道Streambyte是什么,直到您使用标志-isystem <pathToStdHeaderDirectory>手动插入标准标题为止

我编写了一个C#函数,用于检索所有Visual Studio VC标头,包括目录:

    private static string[] GetStdIncludes()
    {

        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\VisualStudio"))
        {
            if (key != null)
            {
                var lastVcVersions = key.GetSubKeyNames()
                    .Select(s =>
                    {
                        float result = 0;
                        if (float.TryParse(s, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result))
                            return result;
                        else return 0F;

                    }).Where(w => w > 0F)
                    .OrderByDescending(or => or)
                    .Select(s => s.ToString("n1", System.Globalization.CultureInfo.InvariantCulture))
                    .ToArray();

                foreach (var v in lastVcVersions)
                {
                    using (var vk = key.OpenSubKey(v))
                    {
                        var val = (string)vk.GetValue("Source Directories");

                        if (!string.IsNullOrEmpty(val))
                            return val.Split(";");
                    }
                }


            }
        }
        throw new Exception("Couldn't find VC runtime include directories");
    }

希望有帮助

答案 2 :(得分:1)

我在自己的班级遇到同样的问题。

您需要将用于编译的相同标志传递给clang_parseTranslationUnit或clang_createTranslationUnit,特别是-I标志,用于查找类或类型定义所在的头文件。 似乎如果libclang找不到类型声明,那么它只是默认为int。

调用clang_createIndex(1,1)应该通过stderr为你提供缺少的提示。

以下是一些现在适合我的示例代码:

int main ( int argc, char* argv[] )
{
    char *clang_args[] =
    {
        "-I.",
        "-I./include",
        "-I../include",
        "-x",
        "c++",
        "-Xclang",
        "-ast-dump",
        "-fsyntax-only",
        "-std=c++1y"
    };
    CXIndex Idx = clang_createIndex ( 1, 1 );
    CXTranslationUnit TU = clang_parseTranslationUnit ( Idx, argv[1], clang_args, 9, NULL, 0, CXTranslationUnit_Incomplete | CXTranslationUnit_SkipFunctionBodies );
    clang_visitChildren ( clang_getTranslationUnitCursor ( TU ),
                          TranslationUnitVisitor, NULL );
    clang_disposeTranslationUnit ( TU );
    return 0;
}

我正在尝试获取头文件的AST,因此CXTranslationUnit_Incomplete | CXTranslationUnit_SkipFunctionBodies标志和-ast-dump -fsyntax-only命令行选项,如果您不需要它们,可能需要省略它们,当然也可以根据需要添加和更改-I参数。