在C++ Builder中是否有类似Delphi的扩展RTTI?

Rud*_*uis 7 delphi c++builder

上下文

(下面的实际问题)

在Delphi中很容易

我经常将API头转换为Delphi.有时结构对齐有问题,或者我想念包装选项#pragma pack(push, 1).要检查我是否具有正确的对齐和大小,我使用扩展的RTTI通过这个简单的函数在我的翻译记录中显示偏移量:

procedure WriteOffsets(Info: Pointer);
var
  LContext: TRttiContext;
  LType: TRttiType;
  LField: TRttiField;
begin
  LType := LContext.GetType(Info);
  if Assigned(LType) then
    if LType.TypeKind = tkRecord then
    begin
      Writeln(('  ' + LType.QualifiedName + ' = record ').PadRight(48),
        ' // size ', LType.TypeSize);
      for LField in LType.GetFields do
        Writeln(('    ' + LField.Name + ': ' + LField.FieldType.Name + ';').PadRight(48),
          ' // offset ', LField.Offset);
      Writeln('  end;');
      Writeln;
    end
    else
    begin
      Writeln(LType.QualifiedName, ' is not a record');
    end
  else
    Writeln('Invalid type');
end;
Run Code Online (Sandbox Code Playgroud)

然后用以下方法调用它:

WriteOffsets(TypeInfo(TSecurityDescriptor));
Run Code Online (Sandbox Code Playgroud)

这很好地写了每个成员字段的大小和偏移量,所以我可以用C++ Builder生成的类似输出来检查它.该函数生成如下内容:

  Winapi.Windows._SECURITY_DESCRIPTOR = record   // size 20
    Revision: Byte;                              // offset 0
    Sbz1: Byte;                                  // offset 1
    Control: Word;                               // offset 2
    Owner: Pointer;                              // offset 4
    Group: Pointer;                              // offset 8
    Sacl: PACL;                                  // offset 12
    Dacl: PACL;                                  // offset 16
  end;
Run Code Online (Sandbox Code Playgroud)

在C++ Builder中不那么容易

但在C++ Builder中,这并不容易.我目前使用了许多宏和简单的RTTI(typeid(x).name()),如下所示:

members.h

#ifndef MEMBERS_H
#define MEMBERS_H

void print_member(const char *type, const char *name, int offset)
{
    char buffer[256];
    sprintf(buffer, "    %s %s;", type, name);
    printf("%-48s // offset %d\n", buffer, offset);
}

#define print(member) \
    print_member(typeid(((type *)0)->member).name(), #member, offsetof(type, member))

#define start \
    printf("struct %-42s/\/ size %d\n{\n", typeid(type).name(), sizeof(type))

#define end \
    printf("};\n\n");

#endif
Run Code Online (Sandbox Code Playgroud)

我知道这很丑陋,让C++纯粹主义者感到畏缩,但它确实有效.我在像这样的简单测试程序中使用它:

#include "windows.h" // for the struct type I want to inspect
#include "members.h"

int main()
{    
    #define type SECURITY_DESCRIPTOR
    start;
        print(Revision);
        print(Sbz1);
        print(Control);
        print(Owner);
        print(Group);
        print(Sacl);
        print(Dacl);
    end;
    #undef type
}
Run Code Online (Sandbox Code Playgroud)

我得到这种输出:

struct _SECURITY_DESCRIPTOR                      // size 20
{
    unsigned char Revision;                      // offset 0
    unsigned char Sbz1;                          // offset 1
    unsigned short Control;                      // offset 2
    void * Owner;                                // offset 4
    void * Group;                                // offset 8
    _ACL * Sacl;                                 // offset 12
    _ACL * Dacl;                                 // offset 16
};
Run Code Online (Sandbox Code Playgroud)

有没有办法让C++ Builder更加优雅和高效?理想情况下,我只提供类型(例如SECURITY_DESCRIPTOR),代码为其所有数据成员生成输出.

目前,与Delphi示例不同,我必须明确查询每个成员字段.我确实得到了我需要的输出,但它比Delphi要多得多.

我找不到让C++ Builder生成类似于Delphi中的扩展RTTI的RTTI的方法.有没有办法,使用C++(或实际上是C++ Builder)的更多扩展功能,例如模板和/或C++ 11(或C++ 14?)的新功能来更好地自动化,即我只是提供结构的名称和代码与Delphi相同?C++ Builder是否提供比普通C++提供的RTTI的基本一点点更好的RTTI?

注意

我只对简单(Windows 32或64位)POD API结构的数据成员感兴趣,而不是在通用C++中使用的具有(可能是虚拟的)成员函数的类或结构中.