2016-08-25 1 views
9

이전에 물어 보았지만 일부 C++ 구조체/공용체를 Delphi로 변환하려고 시도했지만 Hikvision SDK를 사용하지 못했습니다.C++ 유니온을 Delphi로 변환하는 방법

는 C++ 구조/I 변환하기 위해 노력하고있어 노동 조합은 다음과 같습니다 :

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; 

그리고 나는 또한 중첩 기록으로 그것을 가지고 시도 : 나는 다음을 시도

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; 

(여기에 제안 된대로 http://rvelthuis.de/articles/articles-convert.html#unions)

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; 

나는 여기에 비슷한 질문을 보았다. (즉, How do I translate a C union into Delphi?),하지만 내 예제의 조합은 구조의 중간에 있으며, case 문의 'end'도 이해할 수 있으므로 레코드가 종료됩니다.

case 문에서 필드에 대해 동일한 메모리 할당을 사용하는 변형 된 레코드의 이론을 이해한다고 생각하므로 사용되는 필드는/또는 중 하나가 될 수 있지만 어떻게 작동하지 못하는지는 방법을 알려주는 방법입니다 DLL은 struName.unionName.fieldName이든 struName.fieldName이든 관계없이이 레코드를 액세스합니다. 또한 공용체가 정의되는 방식 (즉, case 문의 선택자는 무엇이며 선택기의 데이터 유형을 아는 방법)입니다.

번역 할 세 개의 유사한 구조가 있습니다. 하나를 깰 수 있으면 그림을 그릴 수 있습니다.

위에서 설명한대로, 'Parameter error'라는 오류 메시지가 계속 나타납니다. DLL에서 함수를 호출하는 동안 SDK API의 입력 또는 출력 매개 변수가 NULL 임 (자세한 정보가 필요하면 질문하십시오), 내 레코드가 올바르게 변환되지 않았다고 생각하게 만듭니다.

HCNetSDK.dll SDK 버전 5.0.3.20을 사용하고 있으며 IDE가 XE7 인 경우 도움이됩니다.

도움을 주시면 감사하겠습니다.

+2

FWIW, 레코드 및 유니온 변환에 대한 자세한 내용은 다음을 참조하십시오. http://rvelthuis.de/articles/articles-convert.html#unions 그러나 @DavidHeffernan이 이미 말했듯이 변환은 괜찮지 만 정렬은 꺼져있을 수 있습니다. 이 기사에는 정렬에 관한 섹션도 있습니다. –

+0

이것은 속마음입니다. https://stackoverflow.com/search?q=%5Bdelphi%5D+union –

+0

정말 속마음 아님이 아닙니다. 묻는 사람은 좋은 연구를했으며 결과 코드가 예상대로 작동하지 않는 이유를 알고 싶어합니다. –

답변

6

구조 정렬 설정이 일치한다고 가정하면 공용체를 변환하려는 두 시도가 모두 올바른 것입니다. 당신이 선호하는 것을 사용할 수 있습니다. 그것이 가치있는 일이라면, 당신이 노동 조합을 대표하는 타입을 선언하는 첫 번째 접근법을 선호 할 것입니다.

실제 문제가 무엇이든간에 조합 변환으로 표시되지 않습니다. 이를 테스트하는 간단한 방법은 C++ 및 Delphi 버전에서 유형의 크기가 일치하는지 확인하고 각 멤버의 오프셋이 일치하는지 확인하는 것입니다.

테스트의 경우 유형의 크기는 C++에서 sizeof이고 델파이에서는 SizeOf을 사용합니다. 오프셋의 경우 C++ 용 offsetof 매크로를 사용하고 Delphi 용 my answer here으로 표시된 트릭을 사용하십시오.

+0

사실, 그것에 대해 생각해보십시오 : 노조의 적절한 전환은 아마 포장 된 기록을 사용해야합니다. AFAIK, C 표준은 모든 요소가 같은 주소에 정렬되도록 의무화하고 있지만 Delphi 표준은 없으며 현재 사용중인 모든 컴파일러에 해당되는지 여부를 알지 못합니다. 압축 된 레코드는 모든 부분이 같은 주소. –

+2

@RudyVelthuis 우리는 전에 여러 번이 토론을 가졌습니다. Packed는 레코드를 정렬하도록 강제합니다. 가변 레코드는 항상 변형 멤버를 동일한 오프셋에 배치하기 때문에 레이아웃에 아무런 영향을 미치지 않습니다. 그러나 그것은 구조의 정렬 불일치로 이어질 것입니다. 예를 들어 int와 double을 포함하는 공용체는 크기가 8이고 정렬이 8입니다. 정렬 할 때 항상 8 바이트 경계에 배치해야합니다. 당신이 그것을 포장한다면 그것은 일어나지 않을 것입니다. C++ 코드가 노동 조합에 정렬 1을 강제로 적용한 경우 패킹하십시오. 그렇지 않으면 패킹하지 마십시오. –

+0

@David 시간 내 질문에 대답 해 주셔서 감사합니다. 적어도 지금은 어디에서든지 내 실수가 어디에 있는지 볼 수 있습니다. 그렇다면 조합의 선택자를 정의하는 것은 무엇입니까? –

관련 문제