Ik heb een klein vraagje.. Ik ben nog niet zo heel lang aan het programmeren met C++ en ik
heb nu een message.cpp waar ik een bericht klaar zet in een unsigned char Mes87[8];
Het bericht wordt goed klaar gezet.
Mes87 bevat 8 bytes. deze 8 bytes zijn ook unsigned chars.
Bijvoorbeeld Mes87[0] = 0x02 enz.
Nu moet ik im mij main.cpp deze mes87 ophalen om hem naar de comport te sturen.
Ik krijg het alleen niet voor elkaar om deze message op te halen.
Ik ben niet echt thuis in C++ en heb dus wat moeite met pointers ed..
Dit werkt bijvoorbeeld niet..:
unsigned char getmessage()
{
return Mes87;
}
Je moet de referentie naar de array ophalen. Is alweer een tijdje geleden dat ik met C++ gewerkt heb, maar het is mij niet gelukt om de inhoud van een array te retourneren in een functie.
Overigens is het wel verstandig om dan in je main.cpp de inhoud te kopieren in een nieuwe array, om te voorkomen dat je daar de inhoud van het originele array gaat wijzigen.
De functie moet 8 bytes teruggeven, niet 1. Dat doe je inderdaad met pointers (of met een echte class, als je OO gebruikt). Het return statement is correct, return Mes87 doet precies wat je wil. Alleen, het gedeclareerde type is inderdaad anders. Dat zou dus een pointer moeten zijn. Omdat het niet de bedoeling is daarmee Mes87 te veranderen, is het een const pointer. Je krijgt dan dus
C++:
1
2
3
unsignedcharconst*getMessage(){returnMes87;}
Nou wil je in het algemeen ook meegeven hoeveel bytes er in de message zitten. Dat is in dit geval altijd 8, dat moet je als aanroeper van getMessage maar weten.
Tegenwoordig gebruiken we in C++ daarom een std::vector<unsigned char> Mesg87(. Die heeft een size() member (en een resize, en nog veel meer).
[
Voor 3% gewijzigd door
MSalters op 14-03-2005 11:58
]
Man hopes. Genius creates. Ralph Waldo Emerson Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Als je niet zo handig bent met pointers zou ik in functies geen pointers gaan retourneren. De kans is groot dat je memory leaks krijgt of dat je er opeens achter komt dat hetgeen waarnaar de pointer verwijst al gedeleted is. Dit soort dingen zijn mooi om de performance op te krikken, maar je moet wel precies weten waar je mee bezig bent.
Ik zou een aparte struct maken voor je message, en die verder gebruiken in je programma. Deze wordt dan constant 'by value' gekopieerd, en als hij uit scope gaat (niet meer nodig is), automatisch gedeleted. Dit programmeert een stuk intuitiever, denk ik.
Dus:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
structMessage{unsignedchardata[8];};MessagegetMessage(){MessageresultMsg;//Vul resultMsg met juiste dataresultMsg.data[0]=0x01;resultMsg.data[1]=0xFE;//..etc.returnresultMsg;}//In je aanroepende code:MessagereceivedMsg=getMessage();
[
Voor 13% gewijzigd door
MrBucket op 14-03-2005 12:06
]
Alleen ik heb al een struct voor de message maar converteer deze juist naar een array.
Dit doe ik omdat de waarden van de bytes in een struct niet exact na elkaar komen in het geheugen.
In een array is dit wel het geval.
Ik moet namelijk zeker weten dat als ik de message door geef aan de com-port dat dan de juist bytes worden ontvangen zonder gaten ertussen.
Aha
Ik weet niet met welke compiler je werkt, maar op MSVC++ bestaat er een #pragma pack()-directive, waarmee je de alignment van je data kan bepalen.
Normaal gesproken zal een compiler proberen om al je data zoveel mogelijk op adressen te plaatsen die een veelvoud zijn van 8, omdat ze dan sneller te benaderen zijn door de processor. Nadeel is idd dat er dan 'gaten' kunnen vallen tussen de verschillende velden van je struct.
C++:
1
2
3
4
5
6
#pragma pack(push) //Sla huidige alignment op#pragma pack(1) //Align op byte-grenzen (dus geen 'gaten')structMessage{//Declaratie van Message komt hier};#pragma pack(pop) //Herstel alignment
Dit zou ervoor moeten zorgen dat in je struct alle datavelden zonder 'gaten' achter elkaar komen in het geheugen.
[
Voor 4% gewijzigd door
MrBucket op 14-03-2005 12:21
]
Alleen ik heb al een struct voor de message maar converteer deze juist naar een array.
Dit doe ik omdat de waarden van de bytes in een struct niet exact na elkaar komen in het geheugen.
In een array is dit wel het geval.
Ik moet namelijk zeker weten dat als ik de message door geef aan de com-port dat dan de juist bytes worden ontvangen zonder gaten ertussen.
Als je in je struct een array declareert zoals in het voorbeeld hierboven, dan zullen in ieder geval die bytes na elkaar komen in het geheugen. En ik meen me te herrinneren van school dat ook in een structure de adressen elkaar opvolgen, maar ik kan me vergissen.
Ik weet niet met welke compiler je werkt, maar op MSVC++ bestaat er een #pragma pack()-directive, waarmee je de alignment van je data kan bepalen.
Normaal gesproken zal een compiler proberen om al je data zoveel mogelijk op adressen te plaatsen die een veelvoud zijn van 8, omdat ze dan sneller te benaderen zijn door de processor. Nadeel is idd dat er dan 'gaten' kunnen vallen tussen de verschillende velden van je struct.
C++:
1
2
3
4
5
6
#pragma pack(push) //Sla huidige alignment op#pragma pack(1) //Align op byte-grenzen (dus geen 'gaten')structMessage{//Declaratie van Message komt hier};#pragma pack(pop) //Herstel alignment
Dit zou ervoor moeten zorgen dat in je struct alle datavelden zonder 'gaten' achter elkaar komen in het geheugen.
Inderdaad het gebruik van pragma kan inderdaad werken alleen ik ben de code nu in C++ aan het maken, maar het is de bedoeling dat het dadelijk in C geschreven word met de borland C compiler.
De vraag is of deze pragma ondersteund maar ik denk het niet. Toen kreeg ik de tip om het met een array te doen.
Waarom doe je de conversie naar een array niet helemaal aan het eind, dus net voordat je em wilt versturen? Kun je in de rest van je app gewoon met die struct werken.
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
Ik vraag me alleen af of ik de de juiste oplossing heb.. Met name het writefile gedeelte??
Het bericht stelt een dome (koepel camera) aanroep voor. Dit bericht moet dus naar de camera toe worden gestuurd en deze hoort daarna te reageren.. Dit gebeurd dus niet. Ik ben bang dat ik een fout maak in mijn writefile procedure..
voidmain(void){HANDLEhCommPort;charcomStr[5];unsignedintcomport;unsignedlongbaudrate;unsignedlonglineCounter=0;initMessageTypes();setTestMessages();printArrayValues();//open the COM Portcomport=3;baudrate=9600;switch(comport){case1:strcpy(comStr,"COM1");break;case2:strcpy(comStr,"COM2");break;case3:strcpy(comStr,"COM3");break;case4:strcpy(comStr,"COM4");break;default:strcpy(comStr,"COM1");break;}hCommPort=CreateFile(comStr,GENERIC_READ|GENERIC_WRITE,//access ( read and write)0,//(share) 0:cannot share the COM port 0,//security (None) OPEN_EXISTING,// creation : open_existing0,0// no templates file for COM port...);if(hCommPort==INVALID_HANDLE_VALUE){printf("Could not open %s\n",comStr);}else{printf("%s opened succesfully at %lu baud",comStr,baudrate);}if(!SetCommMask(hCommPort,0)){printf("SetCommMask failed\n");}DCBdcb={0};dcb.DCBlength=sizeof(DCB);if(!GetCommState(hCommPort,&dcb)){printf("GetCommState failed\n");}dcb.BaudRate=baudrate;dcb.ByteSize=8;dcb.Parity=0;dcb.StopBits=ONESTOPBIT;dcb.fDsrSensitivity=0;dcb.fDtrControl=DTR_CONTROL_ENABLE;dcb.fOutxDsrFlow=0;if(!SetCommState(hCommPort,&dcb)){printf("SetComState failed\n");}//now set the timeouts ( we control the timeout overselves using WaitForXXX()COMMTIMEOUTStimeouts;timeouts.ReadIntervalTimeout=MAXDWORD;timeouts.ReadTotalTimeoutMultiplier=0;timeouts.ReadTotalTimeoutConstant=0;timeouts.WriteTotalTimeoutMultiplier=0;timeouts.WriteTotalTimeoutConstant=0;if(!SetCommTimeouts(hCommPort,&timeouts)){printf("SetComTimeouts Failed\n");}SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlBreakHandler,TRUE);while(Running){DWORDdwBytesWritten=0;WriteFile(hCommPort,MesAr86,8,&dwBytesWritten,NULL);MesAr86[2]<0x0F?MesAr86[2]++:MesAr86[2]=0x01;}CloseHandle(hCommPort);printf("COM port closed\n");}
[
Voor 6% gewijzigd door
.oisyn op 14-03-2005 17:00
]
Je hebt een hele strakke loop die niets anders doet dan prut versturen.
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
Verwijderd schreef op maandag 14 maart 2005 @ 13:45:
[...]
Inderdaad het gebruik van pragma kan inderdaad werken alleen ik ben de code nu in C++ aan het maken, maar het is de bedoeling dat het dadelijk in C geschreven word met de borland C compiler.
De vraag is of deze pragma ondersteund maar ik denk het niet. Toen kreeg ik de tip om het met een array te doen.
#pragma is compiler specifiek. Moet je idd niet doen. Zeker niet als je zoals hier een goed alternatief hebt.
Alleen, mensen halen hier twee dingen door elkaar. Er zitten geen gaten in een array, in een struct soms. Wat sommigen dan ten onrechte denken is dat er toch gaten in een array kunnen zitten, als die in een struct zit. Nee dus. Maak een char[8] aan binnen een struct, en je weet zeker dat er geen gat in die 8 bytes zitten. Bovendien maakt je C++ compiler dan een copy ctor voor je.
Als je later met C wil gaan werken, bereid je dan maar voor op een boel extra werk. C en C++ zijn twee talen die wel verwantschap hebben, maar toch verschillend zijn.
Man hopes. Genius creates. Ralph Waldo Emerson Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Oftewel; hij verhoogt MesAr82[2] met 1, maar als 'ie 0x10 wordt, wordt 'ie weer 1 (een soort modulo 0x10 waarbij de 0 niet mee doet).
Waarom dat in een conditionele expressie staat en niet in een veel duidelijker if-then-else statement is me een raadsel. (Of nog beter: MesAr86[2] = 1 + MesAr86[2]%15;)
[
Voor 21% gewijzigd door
Soultaker op 14-03-2005 16:37
]
Mijn vraag is serieus.. Ik verwacht ook een serieus antwoord!
Mijn antwoord is serieus en ik weet ook redelijk waar ik het over heb.
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
MrBucket schreef op maandag 14 maart 2005 @ 12:20:
Normaal gesproken zal een compiler proberen om al je data zoveel mogelijk op adressen te plaatsen die een veelvoud zijn van 8, omdat ze dan sneller te benaderen zijn door de processor.
Nee, niet veelvouden van 8, onder MSVC++ is het veelvouden van min(sizeof(T), k) waarbij T het primitieve type is dat uitgelijnd moet worden, en k is default 8 maar kun je instellen. 3 chars in een struct zal dus een grootte van 3 hebben, niet van 24. 2 chars gevolgd door een int wordt 8 bytes, want de int wordt gealigned op 4 bytes.
Daarnaast mag een compiler hele private, protected en public blokken naar eigen inzicht herrangschikken, dus je hebt sowieso al nooit de garantie dat een public int die achter een private char staat ook in het geheugen erachter staat (al dan niet met padding). Ik ken echter geen compilers die dit ook daadwerkelijk doen, maar feit blijft dat het kán
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Oftewel; hij verhoogt MesAr82[2] met 1, maar als 'ie 0x10 wordt, wordt 'ie weer 1 (een soort modulo 0x10 waarbij de 0 niet mee doet).
Waarom dat in een conditionele expressie staat en niet in een veel duidelijker if-then-else statement is me een raadsel. (Of nog beter: MesAr86[2] = 1 + MesAr86[2]%15;)
Weet je 't zeker? Ik heb even geen standaard bij de hand, maar het parsen van ?: is berucht subtiel. ?: is ook een van de redenen waarom je niet met een operator precedence tabel kunt werken. In elk geval zet ik hier altijd haakjes bij, en dat is een van de weinige gevallen. (Vind het niet de moeite waard om dat te onthouden; 90% van de C++ programmeurs weet het ook niet en dan zijn die haakjes toch nodig. )
Man hopes. Genius creates. Ralph Waldo Emerson Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Mja, ik zet(te) er zelf ook altijd haakjes bij, maar ik probeer dat een beetje af te leren, vooral ook omdat C-programmeurs de neiging hebben zo weinig mogelijk haakjes te gebruiken en dan is het wel fijn als je de code toch kan lezen.
Mijn man-page vindt dat dit de volgorde is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Operator Associativity
-------- -------------
() [] -> . left to right
! ~ ++ -- - (type) * & sizeof right to left
* / % left to right
+ - left to right
<< >> left to right
< <= > >= left to right
== != left to right
& left to right
^ left to right
| left to right
&& left to right
|| left to right
?: right to left
= += -= *= /= %= <<= >>= &= ^= |= right to left
, left to right
Dus ?: staat alleen boven assignment en die komma-expressie, wat doet vermoeden dat alles om de ?: heen eerst gebonden wordt (vergelijk met bv. * die 'boven' + staat). Kan zijn dat de operator precedence in C++ anders is dan in C, maar dat lijkt me sterk toch?
Het gaat inderdaad vaak fout bij dit soort code:
C:
1
a=b-conditie?0:1;/* == (b - conditie) ? 0 : 1 */
En ik kan me voorstellen dat die or/and operators ook verwarring veroorzaken.
[
Voor 31% gewijzigd door
Soultaker op 14-03-2005 17:43
]
Het probleem is dat de C++ grammatica expliciet niet in termen van een operator precedence is geschreven, maar met productie regels. Die man table is misleidend in subtiele gevallen.
Man hopes. Genius creates. Ralph Waldo Emerson Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
...maar ik geloof niet dat TS telepatisch is, dus als je dan ook even zou kunnen uitleggen wat hij fout doet zal het een stuk meer helpen, denk ik.
Dat ie niet telepatisch is geloof ik, maar als ie de moeite neemt om zijn eigen (?) code door te kijken zal hij zien dat hij een hele strakke loop heeft waarin ie prut verstuurt. Hij beweert dat hij niets binnenkrijgt en dat kan ook niet al hij geen prut inleest.
Ik heb hem een hint gegeven, ik ga hem niet tot op de letter uitleggen wat ie fout doet en hoe hij het moet oplossen. Ik ga er vanuit dat hij het zelf leuk vind om oplossingen te bedenken.
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
Ik ben er inmiddels al achter wat ik verkeerd doe..
Het is inderdaad prut die ik verstuur..
Het probleem is dat ik een string moet versturen.
Ik moet dus de MesAr86
(die gedefinieerd is als
unsigned char MesAr86[7]
waarbij de inhoud van MesAr86[0] t/m MesAr86[6] ook weer bestaat uit unsigned chars in de vorm van een byte bv: 0x01.)
converteren naar een string.
De enige vraag die ik nog heb is hoe ik dit doe.
laten we zeggen dat de MesAr86 er als volgt uit ziet.
MesAr86[0] = 0x61
MesAr86[1] = 0x61
MesAr86[2] = 0x61
MesAr86[3] = 0x61
MesAr86[4] = 0x61
MesAr86[5] = 0x61
MesAr86[6] = 0x61
Ik wil dan dat de string Hexadecimaal 61 61 61 61 61 61 61 wordt.
Oftewel de string zal worden "aaaaaaa"
Daarna wil ik er nog een '\0' achteraan plakken.
Het probleem is dat ik zo niet echt weet hoe ik dit moet doen.
Over dat if statement dat ik gebruik... De %15 oplossing is waarschijnlijk efficienter. Ik kon er alleen zo snel niet opkomen en die regel werd alleen maar gebruikt om even snel te testen.
Het stelt het camera nummer voor en ik wist ook niet welk nummer de camera had van 1 -15.
Vandaar.
De string is hexadecimaal 61, dat is wat 0x betekent. In ASCII is dat inderdaad 7 'a' s, maar unsigned char is geen ASCII maar een getal. char is vaak wel ASCII (op zich een detail, je high bit is toch niet in gebruik hier).
Man hopes. Genius creates. Ralph Waldo Emerson Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
Uhmm ja dat klopt die moet ik denk ik ook ooit nog eens terug krijgen..
Maar hoe ik dat doe is weer een nieuwe opdracht voor me.. Ik heb me daar nog niet echt mee bezig gehouden.
Waar zou je dan aan denken.. Welke reply zou ik moeten krijgen dan.. Dit deel is me nog niet helemaal duidelijk..
Nou, ik ken het protocol niet, maar ik kan me voorstellen dat deze een reply geeft als het een commando ontvangen heeft. Op die manier kun je dus controleren of de camera je commando goed ontvengen heeft.
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
Oh ok op die manier... Nou ik weet wel de dome camera die ik hier heb.. Bosch gen3 dome.
Die voert het command uit als deze herkend wordt. Zodra hij niet krijgt wat hij verwacht doet ie gewoon niets.. Ik weet dat mijn code werkt aangezien ik mijn dome zie bewegen.
Dus hiervoor hoef ik geen reply te hebben.. Volgens mijn geeft ie wel bv een still-alive message terug.
Tja, als het device niet standalone hoeft te draaien is het geen probleem. Als je er ook een keer bij weg wil lopen is het misschien handig dat je controleert of het commando is aangekomen en evt een retry doet als het niet goed gaat.
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
farlane schreef op woensdag 16 maart 2005 @ 12:04:
Tja, als het device niet standalone hoeft te draaien is het geen probleem. Als je er ook een keer bij weg wil lopen is het misschien handig dat je controleert of het commando is aangekomen en evt een retry doet als het niet goed gaat.
Tja daar zit natuurlijk wel wat in..
Ik denk wel dat de dome op de commando's reageert die ik hem stuur. Op het moment van versturen ben je er altijd bij als gebruiker. Misschien als je de dome als simulatie middel wil gebruiken kan ik me voorstellen dat er domes aangestuurd worden zonder dat er gebruikers bij zijn.
Verder kan ik geen andere toepassing bedenken waarin berichten gestuurd moeten worden zonder dat de gebruiker toestemming geeft voor een actie..
Tja misschien automatisch reageren op bewegingen enzz...