How to define a Type A in Type B and Type B in Type A?

后端 未结 3 1302
抹茶落季
抹茶落季 2021-01-18 03:34

I have two types. One Type A and one Type B. The Problem Type A contains Type B and Type B contains Type A. Such a thing like this won\'t work:

  type
    ty         


        
相关标签:
3条回答
  • 2021-01-18 04:12

    You misunderstood what those C structs represent. That's because a record is a value type: it's stored right there where you declare the variable. So let's do a few levels of recursive declarations, and you'll understand what I mean; Assuming the two structures aren't absolutely identical:

    type
      TA = record
         test1 : TB;
         SomethingElseFromA: Byte;
      end;
    
      TB = record
         test2 : TA;
         SomethingElseFromB: Byte;
      end;   
    

    Structure TA could be rewritten to mean this:

    type
      TA = record
        // Replaced test1 : TB with the actual content of TB, because that's
        // what a record means.
        test1_test2: TA;
        test1_SomethingElseFromB: Byte;
    
        SomethingElseFromA: Byte;
      end;
    

    Of course, we've now got a nice recursive inclusion of self into the TA record, something along the lines of:

      TA = record
        // Replaces test1_test: TA
        test1_test2: TA; // Oops, still not fixed, need to do it again...
        test1_SomethingElseFromB: Byte;
        SomethingElseFromA: Byte;
    
        test1_SomethingElseFromB: Byte;
        SomethingElseFromA: Byte;
      end;
    

    You probably want to use reference types to get something that looks similar, but it's not similar. A reference type is always a pointer, so it's a fixed size; The compiler can allocate it without a problem. This would be valid, using pointers-to-records:

    type
      pTypeB = ^typeB;
      pTypeA = ^typeA;
    
      typeA = record
         test1 : pTypeB;
      end;
    
      typeB = record
         test2 : pTypeA;
      end;
    

    Alternatively you could use classes; That works for the same reason, classes are reference types; they work the same way as pointers. When you declare a variable of pointer-type, the compiler allocates SizeOf(Pointer) bytes.


    Since you've posted the C structs, I can tell they're too long for me to attempt a complete translation, but I can make a few suggestions: You should declare all your types in a single Type block; don't write the Type before each type declaration. This allows you to create the pointer type before the record type, like this:

    Type
      PMyRecord = ^TMyRecord;
    
      // Somewhere in the same Type block
      TMyRecord = record
      end;
    

    For each type that requires pointers-to-records, declare the pointers first thing after the Type keyword, it's simpler that way. Next, you need to identify the C pointers. If there's a * between the name of the data type and the name of the field, that's a pointer. This is usually written like this:

    int *PointerToSomeInt;
    

    But those would be just as valid:

    int * PointerToSomeInt;
    int* VarName1, * VarName1, * VarName3; // Three pointers to integer.
    

    Finally, you'll need to deal with alignment issues. If you can, check the size of the structures on the C side, and then check the size on the Delphi side: you should get the same size. If you don't, you should try a couple of random {$ALIGN} compiler directives before your structure declaration and repeat until you strike the correct alignment. If all else fails you'll need to find what's wrong (what fields are aligned differently on the Delphi side) and put in some alignment bytes to artificially fix it.

    0 讨论(0)
  • 2021-01-18 04:17

    The Delphi translation of the C code you showed would look like this:

    type
      DLPDFDOC = record; // forward declaration
    
      { DLPDFPAGE }
      DLPDFPAGE = record
        Page: CosObj;
        PrintSelect: CosObj;
        PageBBox: ASFixedRect;
        ContentBBox: ASFixedRect;
        Next: ^DLPDFPAGE;
        Angle: PDRotate;
        Doc: ^DLPDFDOC;
        Content: ^DLPDFSTREAM;
        PageNumber: Longint;
        Complete: AnsiChar;
        FontSubstituted: AnsiChar;
        FontMM: AnsiChar;
        FontBad: AnsiChar;
      end;
    
      { DLPDFDOC }
      DLPDFDOC = record
        dliInstance: ^DLPDFINSTANCE;
        pdDoc: PDDoc;
        cosDoc: CosDoc;
        Outlines: ^DLPDFOUTLINE;
        PDFFileName: PAnsiChar;
        PDFPostFileName: PAnsiChar;
        LastPageEnd: DLPOS;
        BeforeDef: DLPOS;
        DocBBox: ASFixedRect;
        PageCount: Longint;
        PageTreeWidth: Longint;
        PageTreeDepth: Longint;
        PageTreeDepthUsed: Longint;
        AllPages: ^DLPDFPAGETREEARRAY;
        AllFonts: ^DLPDFFONTLIST;
        AllForms: ^DLPDFFORMLIST;
        AllColors: ^DLPDFFORMLIST;
        AllImages: ^DLPDFIMAGELIST;
        AllSpotColors: ^DLPDFSPOTCOLORLIST;
        AllPatterns: ^DLPDFSPOTCOLORLIST;
        AllExtGStates: ^DLPDFEXTGSTATELIST;
        PageList: ^DLPDFPAGE;
        LastPage: ^DLPDFPAGE;
        DeferedDests: ^DLPDFDEST;
        signatureHolder: ^DLPDFSIGNATURE;
        AcroFormBase: ^DLPDFACROFORM;
        PatternColorObj: CosObj;
        PatternColorRGBObj: CosObj;
        PatternColorCMYKObj: CosObj;
        PatternColorGrayObj: CosObj;
        PrintSelect: CosObj;
        PrintSelectCriteria: CosObj;
        IdentH: CosObj;
        IdentV: CosObj;
        DocumentEncoding: ASAtom;
        FontCount: Longint;
        FormCount: Longint;
        PatCount: Longint;
        ImageCount: Longint;
        Compress: AnsiChar;
        Linearize: AnsiChar;
        PageTreeComplete: AnsiChar;
        EmbedFonts: AnsiChar;
        PatternColorsDefined: AnsiChar;
        MakeThumbNails: AnsiChar;
        psSevenBitSafe: ASBool;
        EncryptKeyByteCount: ASInt32;
        condenseResDicts: AnsiChar;
        resourceDict: CosObj;  
        pdfMajorVer: ASInt16;    
        pdfMinorVer: ASInt16;    
        InclRes: ^DLPDFINCLUDEDRES;       
        AllShadings: ^DLPDFSPOTCOLORLIST;
        ShadeCount: Longint;
      end;
    
    0 讨论(0)
  • 2021-01-18 04:28

    Perhaps the best solution is to rethink the design. But you might also be interested in so-called forward declarations of classes:

    type
      TTypeB = class;
    
      TTypeA = class
        test: TTypeB;
      end;
    
      TTypeB = class
        test: TTypeA;
      end;      
    

    SIC! This only works for classes, not records.

    0 讨论(0)
提交回复
热议问题