Comment définir un type A dans le type B et un type B dans le type A?

J’ai deux types. Un type A et un type B. Le type de problème A contient le type B et le type B contient le type A. Une telle chose ne fonctionnera pas:

type typeA = record test1 : typeB; end; type typeB = record test2 : typeA; end; 

Edit: Ce n’est pas ma conception. Je convertis des fichiers d’en-tête C (pour accéder à une DLL) contenant de telles constructions en delphi.

Edit2: “Les structures C ++ sont un autre nom pour les classes AFAIR. Et il doit y avoir des pointeurs, pas des valeurs elles-mêmes. – Arioch ‘Il y a 1 minute” Oui, vous avez raison, c’était un pointeur sur un type:

Là j’ai défini:

 test1 : ^typeB; 

Cela fonctionnera-t-il à la place?

 test1 : Pointer; 

Edit3: Les structures en C:

 /* DLPDFPAGE */ typedef struct dlpdfpage { CosObj Page; CosObj PrintSelect; ASFixedRect PageBBox; ASFixedRect ContentBBox; struct dlpdfpage *Next; PDRotate Angle; struct dlpdfdoc *Doc; DLPDFSTREAM *Content; long PageNumber; char Complete; char FontSubstituted; char FontMM; char FontBad; } DLPDFPAGE; /* DLPDFDOC */ typedef struct dlpdfdoc { DLPDFINSTANCE *dliInstance; PDDoc pdDoc; CosDoc cosDoc; DLPDFOUTLINE *Outlines; char *PDFFileName; char *PDFPostFileName; DLPOS LastPageEnd; DLPOS BeforeDef; ASFixedRect DocBBox; long PageCount; long PageTreeWidth; long PageTreeDepth; long PageTreeDepthUsed; DLPDFPAGETREEARRAY *AllPages; DLPDFFONTLIST *AllFonts; DLPDFFORMLIST *AllForms; DLPDFFORMLIST *AllColors; DLPDFIMAGELIST *AllImages; DLPDFSPOTCOLORLIST *AllSpotColors; DLPDFSPOTCOLORLIST *AllPatterns; DLPDFEXTGSTATELIST *AllExtGStates; DLPDFPAGE *PageList; DLPDFPAGE *LastPage; DLPDFDEST *DeferedDests; DLPDFSIGNATURE *signatureHolder; struct dlpdfacroform *AcroFormBase; CosObj PatternColorObj, PatternColorRGBObj, PatternColorCMYKObj, PatternColorGrayObj, PrintSelect, PrintSelectCriteria; CosObj IdentH, IdentV; ASAtom DocumentEncoding; long FontCount; long FormCount; long PatCount; long ImageCount; char Compress; char Linearize; char PageTreeComplete; char EmbedFonts; char PatternColorsDefined; char MakeThumbNails; ASBool psSevenBitSafe; ASInt32 EncryptKeyByteCount; char condenseResDicts; CosObj resourceDict; ASInt16 pdfMajorVer; ASInt16 pdfMinorVer; DLPDFINCLUDEDRES *InclRes; DLPDFSPOTCOLORLIST *AllShadings; long ShadeCount; } DLPDFDOC; 

Vous avez mal compris ce que ces structures C représentent. En effet, un record est un type de valeur: il est stocké là où vous déclarez la variable. Faisons donc quelques niveaux de déclarations récursives, et vous comprendrez ce que je veux dire. En supposant que les deux structures ne sont pas absolument identiques:

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

La structure TA pourrait être réécrite pour signifier ceci:

 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; 

Bien sûr, nous avons maintenant une belle inclusion récursive de soi dans l’enregistrement de TA , quelque chose du genre:

  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; 

Vous voulez probablement utiliser des types de référence pour obtenir quelque chose qui ressemble, mais ce n’est pas pareil. Un type de référence est toujours un pointeur; sa taille est donc fixe. Le compilateur peut l’allouer sans problème. Ce serait valide, en utilisant des pointeurs vers des enregistrements:

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

Sinon, vous pouvez utiliser des classes; Cela fonctionne pour la même raison, les classes sont des types de référence; ils fonctionnent de la même manière que les pointeurs. Lorsque vous déclarez une variable de type pointeur, le compilateur alloue des SizeOf(Pointer) .


Puisque vous avez posté les structures C, je peux dire qu’elles sont trop longues pour tenter une traduction complète, mais je peux faire quelques suggestions: Vous devez déclarer tous vos types dans un seul bloc Type ; n’écrivez pas le Type avant chaque déclaration de type. Cela vous permet de créer le type de pointeur avant le type d’enregistrement, comme ceci:

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

Pour chaque type nécessitant des pointeurs vers des enregistrements, déclarez les pointeurs avant le mot-clé Type , ce qui est plus simple. Ensuite, vous devez identifier les pointeurs C. S’il y a un * entre le nom du type de données et le nom du champ, c’est un pointeur. Ceci est généralement écrit comme ceci:

 int *PointerToSomeInt; 

Mais ceux-ci seraient tout aussi valables:

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

Enfin, vous devrez gérer les problèmes d’alignement. Si vous le pouvez, vérifiez la taille des structures du côté C, puis la taille du côté Delphi: vous devriez obtenir la même taille. Si vous ne le faites pas, vous devriez essayer quelques directives de compilateur aléatoires {$ALIGN} avant votre déclaration de structure et répéter l’opération jusqu’à obtenir le bon alignement. En cas d’échec, vous devez rechercher ce qui ne va pas (quels champs sont alignés différemment du côté de Delphi) et insérer des octets d’alignement pour le réparer de manière artificielle.

La meilleure solution est peut-être de repenser le design. Mais vous pourriez aussi être intéressé par les déclarations dites de classes:

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

SIC! Cela ne fonctionne que pour les classes, pas les enregistrements.

La traduction Delphi du code C que vous avez montré ressemblerait à ceci:

 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;