【问题标题】:C Unions in DelphiDelphi 中的 C 联合
【发布时间】:2015-01-01 23:27:00
【问题描述】:

我想翻译来自winnt.h 的一些类型定义,其中包含一些带有位域的联合。但是,这是正确的做法吗?我特别不确定_TP_CALLBACK_ENVIRON_V3 中的联合。

  typedef struct _UMS_SYSTEM_THREAD_INFORMATION {
      ULONG UmsVersion;
      union {
          struct {
              ULONG IsUmsSchedulerThread : 1;
              ULONG IsUmsWorkerThread : 1;
          } DUMMYSTRUCTNAME;
          ULONG ThreadUmsFlags;
      } DUMMYUNIONNAME;
  } UMS_SYSTEM_THREAD_INFORMATION, *PUMS_SYSTEM_THREAD_INFORMATION;

  typedef struct _TP_CALLBACK_ENVIRON_V3 {
    TP_VERSION                         Version;
    PTP_POOL                           Pool;
    PTP_CLEANUP_GROUP                  CleanupGroup;
    PTP_CLEANUP_GROUP_CANCEL_CALLBACK  CleanupGroupCancelCallback;
    PVOID                              RaceDll;
    struct _ACTIVATION_CONTEXT        *ActivationContext;
    PTP_SIMPLE_CALLBACK                FinalizationCallback;
    union {
        DWORD                          Flags;
        struct {
            DWORD                      LongFunction :  1;
            DWORD                      Persistent   :  1;
            DWORD                      Private      : 30;
        } s;
    } u;
    TP_CALLBACK_PRIORITY               CallbackPriority;
    DWORD                              Size;
} TP_CALLBACK_ENVIRON_V3;

type
  UMS_SYSTEM_THREAD_INFORMATION = record
    UmsVersion: ULONG;
    ThreadUmsFlags: ULONG;
    case Integer of
      0:(IsUmsSchedulerThread : ULONG);
      1:(IsUmsWorkerThread : ULONG);
  end;
  PUMS_SYSTEM_THREAD_INFORMATION = ^UMS_SYSTEM_THREAD_INFORMATION;

  TP_CALLBACK_ENVIRON_V3 = record
    Version: TP_VERSION;
    Pool: PTP_POOL;
    CleanupGroup: PTP_CLEANUP_GROUP;
    CleanupGroupCancelCallback: PTP_CLEANUP_GROUP_CANCEL_CALLBACK;
    RaceDll: PVOID;
    ActivationContext: PACTIVATION_CONTEXT; // Pointer
    FinalizationCallback: PTP_SIMPLE_CALLBACK;
    case Flags: DWORD of
      1: (LongFunction: DWORD)
      1: (Persistent: DWORD)
      30: (Private: DWORD)
    end;
    CallbackPriority: TP_CALLBACK_PRIORITY;
    Size: DWORD;
  end;
  PTP_CALLBACK_ENVIRON = ^TP_CALLBACK_ENVIRON_V3;

【问题讨论】:

    标签: delphi delphi-xe7


    【解决方案1】:

    那些: something 符号是位域。没有直接的 Pascal 等价物。

    但是,由于三个位域组合在一起是一个完整的 dword,因此等效项的大致轮廓如下所示:

    type
      _TP_CALLBACK_ENVIRON_V3 = record
      ...
        FinalizationCallback: PTP_SIMPLE_CALLBACK;
        case Integer of
        1: (Flags: DWord);
        2: (LongFunctionPersistentPrivate: DWord)
      end;
    

    【讨论】:

    • 在现代 Delphi 版本中,记录可以具有方法和属性,因此您可以通过一些适当的位移相当容易地模拟各个位域。
    • John,你不需要关心 TP_CALLBACK_ENVIRON 结构位域的字面翻译,因为回调环境结构仅在线程池 API 内部使用。您不应该访问任何这些字段。因此,将这些位域合并为一个 DWORD 就可以了。您建议的翻译是错误的。 1: (LongFunction: DWORD) 代表DWORD 的第一位,1: (Persistent: DWORD) 的第二位DWORD30: (Private: DWORD)DWORD 的剩余30 位。您已经为那些错误的字段声明了 3 个DWORDs。执行此处的建议。
    • @TLama 谢谢!由于它仅在kernel32.dll 内部使用,我可以只使用指向该结构的不透明指针。 :)
    • 约翰,在这种情况下不是。它在内部使用,但您不能将它(整个 TP_CALLBACK_ENVIRON 结构)定义为不透明指针。该类型必须是完整的,因为分配它的是您的应用程序。 InitializeThreadpoolEnvironment 函数被实现为内联函数,其唯一的业务是返回这种类型的初始化结构(因此它必须是已知的)。
    【解决方案2】:

    如前所述,':' 符号是位字段。没有直接的解决方案,但有一种简单的方法可以翻译它们,使它们再次有用。请参阅描述此内容的我的文章。它使用一组简单的函数来获取或设置一些位并将它们移动到适当的位置,以及使用相当未知的属性索引来声明它们的一种聪明的方法(我没有发明它,顺便说一句)。

    看这里:Pitfalls of converting

    这个想法来自Stack Overflow answer

    FWIW,文章中还描述了how to handle unions这样的翻译。

    【讨论】:

    • FWIW,文章暂时下线。与我的供应商合作使其再次上线。
    猜你喜欢
    • 2017-01-01
    • 2010-09-12
    • 1970-01-01
    • 2012-05-05
    • 2013-01-18
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    相关资源
    最近更新 更多