title: How to convert a C++ union to Delphi
body: <p>I know this has been asked before, but I am unsuccessfully trying to convert some C++ structures/unions to Delphi to use the Hikvision SDK.</p>
  
  <p>The C++ structures/unions I’m trying to convert are as follow:</p>
  
  <pre><code>struct{
    BYTE                           byEnable;
    BYTE                           byRes1[3];
    DWORD                          dwTriggerType;
    NET_ITC_TRIGGER_PARAM_UNION    uTriggerParam;
    BYTE                           byRes[64];
  }NET_ITC_SINGLE_TRIGGERCFG,*LPNET_ITC_SINGLE_TRIGGERCFG;
  
  union{
    DWORD                              uLen[1070];
    NET_ITC_POST_IOSPEED_PARAM         struIOSpeed;
    NET_ITC_POST_SINGLEIO_PARAM        struSingleIO;
    NET_ITC_POST_RS485_PARAM           struPostRs485;
    NET_ITC_POST_RS485_RADAR_PARAM     struPostRadar;
    NET_ITC_POST_VTCOIL_PARAM          struVtCoil;
    NET_ITC_EPOLICE_IOTL_PARAM         struIOTL;
    NET_ITC_EPOLICE_RS485_PARAM        struEpoliceRs485;
    NET_ITC_EPOLICE_RS485_PARAM        struPERs485;
  }NET_ITC_TRIGGER_PARAM_UNION,*LPNET_ITC_TRIGGER_PARAM_UNION;
  </code></pre>
  
  <p>I have tried the following:</p>
  
  <pre><code>  PNetItcSingleTriggerCfg = ^TNetItcSingleTriggerCfg;
    TNetItcSingleTriggerCfg = record
      byEnable:      Byte;
      byRes1:        array [0..2] of Byte;
      dwTriggerType: DWord;
      uTriggerParam: TNetItcTriggerParamUnion;
      byRes:         array [0..63] of Byte;
    end;
  
    PNetItcTriggerParamUnion = ^TNetItcTriggerParamUnion;
    TNetItcTriggerParamUnion = record
      case integer of
        0: (uLen:             array [0..1069] of DWord);
        1: (struIOSpeed:      TNetItcPostIOSpeedParam);
        2: (struSingleIO:     TNetItcPostSingleIOParam);
        3: (struPostRs485:    TNetItcPostRS485Param);
        4: (struPostRadar:    TNetItcPostRS485RadarParam);
        5: (struVtCoil:       TNetItcPostVTCoilParam);
        6: (struHvt:          TNetItcPostHvtParam);
        7: (struIOTL:         TNetItcEPoliceIOTLParam);
        8: (struEpoliceRs485: TNetItcEPoliceRS485Param);
        9: (struPERs485:      TNetItcEPoliceRS485Param);          
        10:(struPostMpr:      TNetItcPostMprParam);
        11:(struViaVtCoil:    TNetDvrViaVtCoilParam);
        12:(struPostImt:      TNetItcPostImtParam);
        13:(struPostPrs:      TNetItcPostPrsParam);
        14:(struIpcHvt:       TNetIpcPostHvtParam);
        15:(struHvtV50:       TNetIpcPostHvtParamV50);
    end;
  </code></pre>
  
  <p>And I have also tried having it as a nested record (as suggested here <a href="http://rvelthuis.de/articles/articles-convert.html#unions">http://rvelthuis.de/articles/articles-convert.html#unions</a> )</p>
  
  <pre><code>  PNetItcSingleTriggerCfg = ^TNetItcSingleTriggerCfg;
    TNetItcSingleTriggerCfg = record
      byEnable:      Byte;
      byRes1:        array [0..2] of Byte;
      dwTriggerType: DWord;
      uTriggerParam: record
        case integer of
          0: (uLen:             array [0..1069] of DWord);
          1: (struIOSpeed:      TNetItcPostIOSpeedParam);
          2: (struSingleIO:     TNetItcPostSingleIOParam);
          3: (struPostRs485:    TNetItcPostRS485Param);
          4: (struPostRadar:    TNetItcPostRS485RadarParam);
          5: (struVtCoil:       TNetItcPostVTCoilParam);
          6: (struHvt:          TNetItcPostHvtParam);
          7: (struIOTL:         TNetItcSingleIOTLParam);
          8: (struEpoliceRs485: TNetItcEPoliceRS485Param); 
          9: (struPERs485:      TNetItcEPoliceRS485Param);
          10:(struPostMpr:      TNetItcPostMprParam);
          11:(struViaVtCoil:    TNetDvrViaVtCoilParam);
          12:(struPostImt:      TNetItcPostImtParam);
          13:(struPostPrs:      TNetItcPostPrsParam);
          14:(struIpcHvt:       TNetIpcPostHvtParam);
          15:(struHvtV50:       TNetIpcPostHvtParamV50);
        end;
      byRes:         array [0..63] of Byte;
    end;
  </code></pre>
  
  <p>I have seen similar questions on here (i.e. <a href="https://stackoverflow.com/questions/13324368/how-do-i-translate-a-c-union-into-delphi">How do I translate a C union into Delphi?</a> ), but the union in my example is in the middle of the structure, and as I understand the ‘end’ of the case statement also ends the record.</p>
  
  <p>I think I understand the theory behind a variant record having the same memory allocation for the fields in the case statement, so the fields used would be either/or, but what I can’t work out is how to tell how the DLL is accessing these records, whether it is struName.unionName.fieldName or struName.fieldName and also how the union is defined (i.e. what is the selector of the case statement, and how to know what data type the selector is). </p>
  
  <p>I have three similar structures to translate, and figure if I can crack one, I can crack them all.</p>
  
  <p>With the records as described above, I keep getting the error message ‘Parameter error. Input or output parameter in the SDK API is NULL’ whilst calling a function from the DLL (if you need more information on this, please ask), which makes me think that my records have not been converted correctly.</p>
  
  <p>I’m using the HCNetSDK.dll SDK version 5.0.3.20 and my IDE is XE7 if that helps.</p>
  
  <p>Any help would be appreciated.</p>