将复杂的struct / opaquepointer / function从C ++头转换为Delphi

时间:2019-02-28 08:56:27

标签: c++ function delphi

我正在从C / C ++头转换为Delphi。 我已经仔细阅读了很棒的Rudy's Delphi Corner关于这种转换的文章。无论如何,我面临着一些我难以理解的事情。

有一个不透明的指针,然后是一个以该指针作为参数的函数原型,然后是结构声明和函数类型。

也许代码会让事情变得更清楚。

源.h代码:

struct my_ManagedPtr_t_;
typedef struct my_ManagedPtr_t_ my_ManagedPtr_t;

typedef int (*my_ManagedPtr_ManagerFunction_t)(
                                            my_ManagedPtr_t *managedPtr,
                                            const my_ManagedPtr_t *srcPtr,
                                            int operation);

typedef union {
    int   intValue;
    void *ptr;
} my_ManagedPtr_t_data_;

struct my_ManagedPtr_t_ {
    void *pointer;
    my_ManagedPtr_t_data_ userData[4];
    my_ManagedPtr_ManagerFunction_t  manager;
};

typedef struct my_CorrelationId_t_ {
    unsigned int  size:8;       // fill in the size of this struct
    unsigned int  valueType:4;  // type of value held by this correlation id
    unsigned int  classId:16;   // user defined classification id
    unsigned int  reserved:4;   // for internal use must be 0

    union {
        my_UInt64_t      intValue;
        my_ManagedPtr_t  ptrValue;
    } value;
} my_CorrelationId_t;

...我迷路了。 :-(我不知道从哪里开始。 结构?功能?

谢谢。

2 个答案:

答案 0 :(得分:2)

正如您在评论中所阐明的那样,给您带来困惑的直接领域是循环引用。函数指针参数引用该结构,但是该结构包含函数指针。在C代码中,这是由不透明的结构类型声明处理的,它只是一个前向声明。前向声明只是承诺该类型将在以后的某个时刻完全声明。

在Delphi中,您可以直接类似的方式处理它。您需要使用前向类型声明。我不想翻译问题中的所有类型,因为这将需要处理我认为是单独主题的并集和位域。相反,我将提供一个简单的Delphi示例,该示例演示如何处理此类循环类型声明。您可以采用该概念并将其应用于您的特定类型。

type
  PMyRecord = ^TMyRecord; // forward declaration
  TMyFunc = function(rec: PMyRecord): Integer; cdecl;
  TMyRecord = record
    Func: TMyFunc;
  end;

答案 1 :(得分:1)

很难找到从哪里开始,但是@DavidHeffernan对向前声明指针类型的解释应该为您提供一个起点。

我会将其翻译为以下( unested )代码:

type
  _my_ManagedPtr_p = ^my_ManagedPtr_t;

  my_ManagedPtr_ManagerFunction_t = function(
    managedPtr: my_ManagedPtr_p;
    scrPtr: my_ManagedPtr_p; 
    operation: Integer): Integer cdecl;

  my_ManagedPtr_t_data = record
    case Boolean of
      False: (intValue: Integer);
      True:  (ptr: Pointer);
  end;

  my_ManagedPtr_t = record
    ptr: Pointer;
    userData: array[0..3] of my_ManagedPr_t_data;
    manager: my_ManagedPtr_ManagerFunction_t;
  end;

  my_CorrelationId_t = record
    typeData: UInt32; // size, valueType, classId and reserved combined in one integer.
    case Byte of
       0: (intValue: my_UInt64_t);
       1: (ptrValue: my_ManagedPtr_t;
  end;

我不会处理位域,但是请再次阅读我的文章Pitfalls of converting Bitfields 部分(我已经看到您已经提到过)以找到一些解决方案。如果您想使其真正好用,请使用方法和索引访问,否则只需使用shifts和masks访问我称为typeData的成员中包含的位域。文章中对此进行了解释,在此不再赘述。

如果您仍然遇到问题,请提出一个新问题。