2016-08-25 17 views
9

Bunun daha önce sorulmuş olduğunu biliyorum, ancak başarısız olmaya çalıştığım bazı C++ yapıları/birimlerini Delphi'ye dönüştürerek Hikvision SDK'yı kullanıyorum.Bir C++ birleşimini Delphi'ye dönüştürme

C++ yapılar/I dönüştürmek çalışıyorum sendikalar aşağıdaki gibidir:

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; 

Ve ayrıca iç içe geçmiş bir rekor olarak sahip denedim: Aşağıdaki denedi

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; 

burada benzer sorular gördük

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; 

(burada http://rvelthuis.de/articles/articles-convert.html#unions önerilen) (Yani How do I translate a C union into Delphi?), fakat benim örneğimdeki birlik yapının ortasında ve vaka ifadesinin "sonunu" anladığımda rekoru da bitiriyor.

Vaka ifadesindeki alanlar için aynı bellek tahsisine sahip bir varyant kaydının arkasındaki teoriyi anlıyorum, bu yüzden kullanılan alanlar ya/veya olabilir, ama ne yapamayacağımı nasıl anlatacağım DLL, struName.unionName.fieldName veya struName.fieldName olsun ve aynı zamanda sendika tanımlanmış olup olmadığı (yani durum ifadesinin seçicisi nedir ve seçicinin hangi veri türünü bildiğini bilmek), bu kayıtlara erişiyor.

Tercüme etmek için üç benzer yapıya sahibim ve bir tane çatlayabilir miyim, hepsini çözebilirim.

Yukarıda açıklandığı gibi kayıtlarda hata mesajını almaya devam ediyorum ‘Parametre hatası. SDK API'sındaki giriş veya çıkış parametresi, DLL'den bir işlev çağrılırken (bu konuda daha fazla bilgiye ihtiyaç duyarsanız, lütfen sorunuz), bu da kayıtlarımın doğru şekilde dönüştürülmediğini düşünür.

HCNetSDK.dll SDK sürüm 5.0.3.20 kullanıyorum ve bu yardımcı olursa IDE XE7'm var.

Herhangi bir yardım için teşekkür ederiz.

+2

FWIW, daha fazla kayıt ve sendikaları buraya dönüştürme hakkında: http://rvelthuis.de/articles/articles-convert.html#unions Ama zaten @DavidHeffernan dediği gibi, dönüşümünüz tamam, ancak hizalama kapalı olabilir. Bu makalede hizalama hakkında bir bölüm de var. –

+0

Aslında bu bir dupe. https://stackoverflow.com/search?q=%5Bdelphi%5D+union –

+0

Gerçekten bir dupe değil. Asker iyi bir araştırma yaptı ve sonuçta ortaya çıkan kodun neden beklendiği gibi görünmediğini bilmek istiyor. –

cevap

6

Yapı hizalama ayarlarının eşleştiğini varsayarsak, birleşimi dönüştürme girişimlerinizin her ikisi de doğrudur. Hangisini tercih ederseniz kullanabilirsiniz. Buna değerse, sendikayı temsil edecek bir tip ilan ettiğin ilk yaklaşımı tercih ederim.

Asıl sorununuz ne olursa olsun, bu, sendika dönüştürmesiyle birlikte görünmemektedir. Bunu sınamanın basit bir yolu, C++ ve Delphi sürümlerinde türlerin boyutunun eşleştiğini ve her bir üyenin eşleşmelerinin eşleştiğini kontrol etmektir.

Bir türün boyutunu sınamak için, C++ ve SizeOf Delphi'de sizeof kullanın. Ofsetler için C++ için offsetof makrosunu ve Delphi için my answer here'da gösterilen numarayı kullanın.

+0

Aslında, bunu düşünün: Bir birliğin düzgün bir şekilde dönüştürülmesi muhtemelen dolu bir kayıt kullanmalıdır. AFAIK, C standardı tüm öğelerin aynı adreste hizalanmasını zorunlu kılar, ancak Delphi standardı yoktur ve şu anda kullanılmakta olan tüm derleyiciler için bunun doğru olup olmadığını bilmiyorum. Paketlenmiş kayıtlar, tüm parçaların hizada olmasını sağlar. aynı adres. –

+2

@RudyVelthuis Bu tartışmayı daha önce defalarca yaptık. Paketlenmiş kayıtların hizalanmasını sağlar. Düzen üzerinde hiçbir etkisi olmayacaktır çünkü bir varyant kaydı her zaman varyant üyelerini aynı ofsete yerleştirir. Ancak yapının yanlış hizalanmasına yol açacaktır. Örneğin, bir int ve bir çift içeren bir sendika 8 ve hizalama 8'e sahiptir. Hizalandığında, her zaman 8 bayt sınırlarına yerleştirilmelidir. Eğer toplarsan o zaman olmayacak. C++ kodu, birliği hizaya 1 sahip olmaya zorlarsa, o zaman paketlemeyin. –

+0

@David Soruyu cevaplamak için zaman ayırdığınız için teşekkür ederiz. En azından hatanın nerede olduğunu görmek için başka bir yere bakabilirim. Peki sendikanın seçicisini ne tanımlar? –

İlgili konular