【问题标题】:retrieve a list of structs defined in a header file检索头文件中定义的结构列表
【发布时间】:2017-08-16 21:14:05
【问题描述】:

我想检索头文件中所有结构的列表,例如CommCtrl.h 中的结构选择:

LVCOLUMNW,LVITEMW,REBARINFO,TVITEMW

这与从结构列表开始并检索其 sizeof 值的更广泛目标有关:

[STRUCT=sizeof64:sizeof32]
LVCOLUMNW=56:44
LVITEMW=88:60
REBARINFO=16:12
TVITEMW=56:40

目前我将 cpp 文件编译为 x64/x32 exe 以确定头文件是否包含结构(失败时返回空白),并确定结构的 sizeof 值:

#define UNICODE 1
#include <iostream>
#include <Windows.h>

int main()
{
    std::cout << sizeof(BITMAPINFOHEADER) << std::endl;
    return 0;
}

如果我可以动态引用结构名称,或者忽略无效的结构名称,那么我可以更有效地做到这一点。

最终我想将上面的代码应用到这个 19486 'Win words' 列表中: http://katahiromz.web.fc2.com/win32/winwords.txt

如果可能的话,另一个想法是检索 Visual Studio 项目中所有当前定义的结构名称的列表。

【问题讨论】:

  • 问题是如果任何应用于sizeof的结构名称无效或未定义,exe将无法编译。因此,要在一个 exe 中对多个结构执行 sizeof,必须定义所有结构。 [回复已删除的评论。]
  • 这不也取决于包装和你如何声明结构吗?如果结构是双精度、布尔值、双精度、布尔值,它将根据包装返回与双精度、双精度、布尔值、布尔值不同的大小。
  • AFAIK x64 和 x32 在 Windows 中具有相同的打包规则,不同之处在于 Ptr/UPtr 在 x64 中的大小为 8,在 x32 中的大小为 4。因此,缺少 Ptr/UPtr 的结构在 x64/x32 中应该是相同的,其他结构在 x64/x32 中将具有不同的偏移量/填充/大小。 -- 我刚刚想到的结构的另一个复杂因素是 if 条件基于 Windows 版本号。
  • 也许(也许很大)以下将有助于找出定义了哪些结构:stackoverflow.com/questions/10711952/… 然后您可以创建一个程序来仅检查已定义结构的大小。
  • 我试过这个脚本,我可以让它与一些实体一起工作,但我无法让它与结构一起工作,尽管我没有那么多 C++ 经验。非常感谢。

标签: c++ struct header-files typedef


【解决方案1】:

这里是一些临时代码,用于通过 AHK 列出头文件(.h 文件)中的结构,然后通过 C++ 检索它们的大小。生成的列表不能保证 100% 完整,但该脚本已被证明在检索结构名称方面非常有效。在 CommCtrl.h 和 WinUser.h 上测试。

;AHK v2 script

#Warn
ListLines("Off")

;q:: ;list structs in a header file (.h file) (provisional script)
vPath := "C:\Program Files (x86)\Windows Kits\8.1\Include\um\CommCtrl.h"
;vPath := "C:\Program Files (x86)\Windows Kits\8.1\Include\um\WinUser.h"
if !FileExist(vPath)
{
    MsgBox("error: file not found:`r`n" vPath)
    return
}
vText := FileRead(vPath)
vDoGetNext := 0
vTemp2 := ""
vIndent := ""
VarSetCapacity(vOutput, 1000000*2)
VarSetCapacity(vListDefine, 1000000*2)
oDict := ComObjCreate("Scripting.Dictionary")

;get struct names from 'typedef struct' definitions
;and store potential struct names from '#define' directives
Loop Parse vText, "`n", "`r"
{
    vTemp := LTrim(A_LoopField) ;remove leading spaces/tabs
    vTemp := RegExReplace(vTemp, "[ `t]+", " ")
    vTemp := RegExReplace(vTemp, " //.*")
    if (SubStr(vTemp, 1, 7) = "#define")
    {
        ;ignore numeric definitions etc
        if !RegExMatch(vTemp, "[(\\\-:" Chr(34) "]| \d")
            vListDefine .= vTemp "`r`n"
        continue
    }

    vTemp := A_LoopField
    ;if (vPos := RegExMatch(vTemp, "typedef"))
    if (vPos := RegExMatch(vTemp, "typedef struct"))
    {
        vTemp2 := vTemp
        vIndent := SubStr(vTemp, 1, vPos-1)
        vDoGetNext := 1
    }
    else if vDoGetNext
    && (SubStr(vTemp, 1, StrLen(vIndent)+1) = vIndent "}")
    {
        vTemp := RegExReplace(vTemp, "^[} ]+|[,;].*")
        if !(vTemp = "")
        && !oDict.Exists("" vTemp)
        && !(vTemp = "DUMMYUNIONNAME")
        {
            oDict.Item["" vTemp] := 1
            vOutput .= vTemp "`r`n"
            ;vOutput .= vTemp2 "`t" vTemp "`r`n"
        }
        vDoGetNext := 0
    }
}

;get struct names from stored '#define' directives
;lines of the form '#define newname oldname'
vOutput .= "`r`n"
Loop Parse vListDefine, "`n", "`r"
{
    oTemp := StrSplit(A_LoopField, " ")
    if (oTemp.Length() = 3)
    && !oDict.Exists("" oTemp.2) ;new name not seen before
    && oDict.Exists("" oTemp.3) ;old name seen before
    {
        oDict.Item["" oTemp.2] := 1
        vOutput .= oTemp.2 "`r`n"
    }
}

;get raw list of structs:
;Clipboard := RTrim(vOutput, "`r`n") "`r`n"
;MsgBox(vOutput)

vList := vOutput
VarSetCapacity(vOutput, StrLen(vList)*10*2)
Loop Parse vList, "`n", "`r"
{
    vTemp := A_LoopField
    if (vTemp = "")
    {
        vOutput .= "`r`n"
        continue
    }
    vOutput .= "std::cout << " Chr(34) vTemp "=" Chr(34) " << sizeof(" vTemp ") << std::endl;`r`n"
}

Clipboard := RTrim(vOutput, "`r`n") "`r`n"
oDict := ""
MsgBox("done")
return

使用 AHK 脚本生成的代码的示例 C++ 代码。

//structs get sizes

#include "stdafx.h"
#include <iostream>
#include "Windows.h"
#include "CommCtrl.h"

int _tmain(int argc, _TCHAR* argv[])
{
    std::cout << "TVITEMA=" << sizeof(TVITEMA) << std::endl;
    std::cout << "TVITEMW=" << sizeof(TVITEMW) << std::endl;
    std::cout << "TVITEM=" << sizeof(TVITEM) << std::endl;
    std::getchar();
    return 0;
}

注意:另一种方法是从头文件中检索唯一的字符串,将它们粘贴到 Visual Studio,等待 Visual Studio 为适当的单词着色,将列表复制到写字板,保存为 rtf 文件,然后解析原始rtf 用于彩色单词。

也在这里发布:
C++: list structs in a header file - AutoHotkey Community

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    • 2022-07-30
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多