Extern használata

Processing/Wiring (illetve C) nyelvű programozási fogások, tippek. (AVR-Duino, Arduino, EthDuino, Diecimila, Severino, Nano, LilyPad)
Avatar
csabeszq
Bitfaragó
Hozzászólások: 660
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: Extern használata

HozzászólásSzerző: csabeszq » 2017. június 15. csütörtök, 20:00

Szép és olvasható kódot írni nem bonyolultabb technikailag, mint olvashatatlant.

A modularitás és a fájlokra bontás kéz a kézben jár. Amikor kölyök voltam, az 5000 soros programom miatt panaszkodott a fordító. Én pedig kettévágtam prog1.cpp és prog2.cpp-re utána fordult. :)

Amikor több részre szabdalsz egy kódot, azt ésszel kell csinálni. Az összetartozó részek mennek egy fájlba, nem pedig vonalat húzol valahol és elfelezed. :)

vargham
Tranzisztorgyógyász
Hozzászólások: 160
Csatlakozott: 2014. január 8. szerda, 8:32
Kapcsolat:

Re: Extern használata

HozzászólásSzerző: vargham » 2017. június 16. péntek, 7:45

> Az a gond, hogy ti nagygépes
Én ugyan nem. Nem is láttam még soha nagygépet. Sajnos. :-)
Egszen kicsi gépekkel szoktam dolgozni. 8 bit AVR-től 32 bit ARM-on át a mobiltelefonig. Na, jó. Néha PC is előfordul.

> több személyes fejlesztésben gondolkoztok.
> De a kezdőnek még korai moduláris programozást emlegetni.
Pedig fontos megtanulni. Egyfelől mindenkinek kell másokkal együtt dolgozni. A kezdő amatőrnek is. Mert használja a mások által tervezett és kifejlesztett C nyelvet, fordítót, mikrokontrollert, programkönyvtárat. Meg kell értenie a köztük lévő kapcsolatot, hogyan oszlanak modulokra, stb. Másfelől pedig az első, debuggolhatatlan 3000 soros spagetti után rájön, hogy az úgy nem jó.

Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3212
Csatlakozott: 2008. augusztus 29. péntek, 6:00
Tartózkodási hely: Újkígyós

Re: Extern használata

HozzászólásSzerző: kapu48 » 2017. június 16. péntek, 9:20

"Másfelől pedig az első, debuggolhatatlan 3000 soros spagetti után rájön, hogy az úgy nem jó."
Kezdő ként itt tartunk most!

És próbálkozzunk, kis lépésekben haladni.

vargham
Tranzisztorgyógyász
Hozzászólások: 160
Csatlakozott: 2014. január 8. szerda, 8:32
Kapcsolat:

Re: Extern használata

HozzászólásSzerző: vargham » 2017. június 16. péntek, 10:21

> Kezdő ként itt tartunk most!
> És próbálkozzunk, kis lépésekben haladni.
Erről én azt gondolom, hogy nem az externnél kell kezdeni. Megérteni nem árt, de érdemes a lehető legjobban kerülni a használatát. Ha már modulok, akkor láthatóság, memóriafoglalás, paraméterek átadása, pointerek, stb.
De nem értek hozzá, csak ezt tapasztaltam. ;-)

Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00
Tartózkodási hely: Budapest

Re: Extern használata

HozzászólásSzerző: SzLacus » 2017. június 18. vasárnap, 23:09

Menjünk vissza az alap felvetésemhez, és haladjunk apró lépésekkel. Írjuk meg a villogTikkTakk.ino "játszóteret" egy fájlba úgy hogy a tikk, vagy takk szöveg a változóba egy külön metódusban kerüljön bele. Valahogy így fog kinézni.

Kód: Egész kijelölése

/*
D E K L A R Á C I Ó K
*/
#define LEDPIN 13
#define ALAPIDO 1000
#define DEBUG


/*
G L O B Á L I S    V Á L T O Z Ó K
*/

unsigned long most;
// String szoveg;      // Itt globális, minden elérheti


void setup()
{
   pinMode(LEDPIN,OUTPUT);
   digitalWrite(LEDPIN,LOW);
   Serial.begin(57600);
   while(!Serial);
}

void loop()
{
// extern String szoveg;      // Itt csak deklaráció. Nem itt foglalok neki helyet
   if (most < (millis() - ALAPIDO))
   {
      most = millis();
      digitalWrite(LEDPIN, !digitalRead(LEDPIN));
      tikkTakk();
//       Serial.println(szoveg);   // Ha itt szeretném printelni, akkor kell az extern, mert másik eljárásban létesül a változó
   }
}

/*
M E T Ó D U S O K
*/

void tikkTakk(void){
   String szoveg;      // Itt lokális, csak itt érhető el.
   szoveg = String(digitalRead(LEDPIN) ? "Tikk" : "Takk");
   Serial.println(szoveg);      // Innen szeretném a printet átvinni a loopba. Ehhez ott szükség lesz a "szoveg" változóra
}

Igyekeztem a kódba megjegyzéssel berakni a változtatni szándékozott sorokat, hogy látsszon én hova raktam, és miért. Így talán kiderül mi az amit nem jól gondolok. következzenek a tapaszatalataim.
A dolog lefordul, miért is ne tenné. Aztán a sok olvasgatást kipróbálandó, a "szoveg" változót először hozzuk létre a globális változóknál, és persze vegyük ki a definiálást az al függvényből. Így is lefordul, ezt is várjuk. Ha ekkor a print sort átrakom a loopba, ugyancsak lefordul, mert mindenki tudja mi az a "szoveg".
Most jön az extern. Hagyom a printet a loopban, és a definíciót vissza teszem az alfüggvénybe. A globálisból kiveszem, és a lopp-ba pedig exter-el beteszem a változót. Az olvasottak alapján ennek le kéne fordulnia, de a *.o fájlban kiakad.

Kód: Egész kijelölése

Compiling 'VillogTikkTakk' for 'Arduino Nano w/ ATmega328'
 
ccP1MXa4.ltrans0.ltrans.o*: In function main
ccP1MXa4.ltrans0.o*: (.text.startup+0x262): undefined reference to szoveg
ccP1MXa4.ltrans0.o*: (.text.startup+0x264): undefined reference to szoveg
 
collect2.exe*: error: ld returned 1 exit status

Error compiling for board Arduino Nano w/ ATmega328
Ez az üzenet, pedig a leírás szerint erre való, és így kell használni az extern-t.
Ha beviszem az extern sort az if-en belülre, az sem segít.
És még minden egy fájlban van. Én meg szeretném a setup előtti részt egy definiciok fájlba rakni, és include-olni oda ahonnan azt eltüntetem.
Ugyan így a tikkTakk függvényt a metódusok állományba szetném kipakolni, és helyette include.

Még egy kis észrevétel azon segítőimnek, akik a "kezdőknek ez nem való" tanácsot adják. Hálás vagyok minden segítőnek, de bátortalanul kérdezem, hogyan lesz haladó a kezdőből. Szerintem úgy, hogy amikor felismer egy haladóknak való problémát, akkor azt nem megkerüli és marad az addig tanultaknál. Köszönöm a változókra, meg láthatóságra, stb való intelmeket, tisztában vagyok vele, most pont ennek az emeltebb szintjét próbálom megérteni. Aztán ha megismerem, akkor majd a buktatóival is meg fogok ismerkedni. Utána majd akkor fogom használni, amikor annak ott a helye, és nem használom, ha nem származik belőle előny. De ehhez működésre kéne tudnom bírni azt, amit olvasok, és a leírások szerint működnie kellene.

Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3212
Csatlakozott: 2008. augusztus 29. péntek, 6:00
Tartózkodási hely: Újkígyós

Re: Extern használata

HozzászólásSzerző: kapu48 » 2017. június 19. hétfő, 9:52

Pedig leírtam! Mégsem érted?

A hívó részben kel definiálni a változót (esetedben a loop-ban), nem a meghívottban, ez esetben:

void tikkTakk(void){
String szoveg; // Itt lokális, csak itt érhető el. Csak itt létezik!

} Mikor kilépsz (vissza térsz), megszűnik az itt definiált változó, ezért már nem érhető el többet.

Az extern csak a láthatóságot befolyásolja, az érvényességet nem.

Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3212
Csatlakozott: 2008. augusztus 29. péntek, 6:00
Tartózkodási hely: Újkígyós

Re: Extern használata

HozzászólásSzerző: kapu48 » 2017. június 19. hétfő, 10:26

Ezt a feladatott másképen, kel megoldani.

Kód: Egész kijelölése

// vissza adjuk a szükséges értéket:
String tikkTakk(void){
   String szoveg;      // Itt lokális, csak itt érhető el.
   szoveg = String(digitalRead(LEDPIN) ? "Tikk" : "Takk");
   return szoveg; // itt vissza adjuk a feldolgozott stringet
   //Serial.println(szoveg);      // Innen szeretném a printet átvinni a loopba. Ehhez ott szükség lesz a "szoveg" változóra
}

És a loop-ban:

Kód: Egész kijelölése

Serial.println(tikkTakk()); // itt ki íratjuk a vissza kapott stringet


Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00
Tartózkodási hely: Budapest

Re: Extern használata

HozzászólásSzerző: SzLacus » 2017. június 19. hétfő, 14:01

Köszönöm Kapu48, rávilágítottál, amit nem vettem észre. Hiába láthatnám az extern miatt, ha már nem fog létezni. Este kipróbálgatom a most kapott információkat. Én azt kezdtem magamban kialakítani, hogy amit több helyről szeretnék látni azt globálnak kell létrehozni, és akkor nem kell az extern. Ami ettől még igaz, csak nem biztos, hogy mindíg kell a globál, ami jól jöhet, ha kell a szabad hely másnak.

Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3212
Csatlakozott: 2008. augusztus 29. péntek, 6:00
Tartózkodási hely: Újkígyós

Re: Extern használata

HozzászólásSzerző: kapu48 » 2017. június 19. hétfő, 14:50

Éppen ezért vannak az érték átadó függvények.

Az előző példában is felszabadul a lefoglalt memória:
Serial.println(tikkTakk()); // itt ki íratjuk a vissza kapott stringet
Itt már nem is létezik a: szoveg, a területe felszabadult.

Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00
Tartózkodási hely: Budapest

Re: Extern használata

HozzászólásSzerző: SzLacus » 2017. június 20. kedd, 14:47

A "másképpen" megoldás, az jó és köszönöm, ez is megoldja. Csak pont az alap próbálkozásomat kerüli meg. Visszaadott értékkel megoldható a feladvány, de vegyük észre, hogy a loop-ban létrehozott "szoveg" változónak semmi köze nincs a tikkTakk metódusban létrehozott, és visszaadott azonos nevű változóhoz. Bele tehetném, vagy hozzá konkatenálhatnám, de én hozzá szeretnék férni, ezért próbálkoztam az extern megismerésével.
Az extern-használatával pont azt szerettem volna kikísérletezni, hogy a loopban létrehozott változó értékét változtatom a tikkTakk eljárásban.
Ha a szoveg változót kirakom a loop elé, akkor macerálhatom a loop-ban is, meg a tikkTakk-ban is, jól működik. A próbálkozásom arra irányult, hogy ha loop-ban hozom létre, akkor a tikkTakk-ban tudok-e vele dolgozni. Ehhez elvileg a tikkTakk-ban extern-ként kell meggneveznem, és akkor macerálhatnám. De nem ez a valóság. Úgy gondolom, hogy valahol az Arduino keretrendszer gondoskodik róla, hogy ne tehessem meg. Valószínűleg nem véletlenül nem szerepel az extern az arduino referencia oldalon.
Találkoztam már hasonló eltéréssel amikor const-nak létrehozott változót a címén keresztül próbáltam macerálni. A könyvek szerint így lehetséges a const változó értékének módosítása a c-ben. Arduino alatt ez nekem nem sikerült.
Köszönöm mindenki segítségét, pillanatnyilag az a meglátásom, hogy amit több függvényből kell elérnem azt globálként kell létrehozzam. Akkor nem kell semmi módosító cizella hozzá.

Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00
Tartózkodási hely: Budapest

Re: Extern használata

HozzászólásSzerző: SzLacus » 2017. június 20. kedd, 15:00

Az érdekesség számomra az, hogy több arduino lib-ben találkozhatunk az extern használatával.
például a wire könyvtár .cpp állományában így néz ki.

Kód: Egész kijelölése

extern "C" {
  #include <stdlib.h>
  #include <string.h>
  #include <inttypes.h>
  #include "twi.h"
}

#include "Wire.h"

Nem tudom mit és miért, de extern. Majd még fejlődöm, és kiderül, hogy miként kell és mire érdemes használni, most megköszönve a segítségeket, elteszem az extern-t a "később majd kiderül" fiókomba.

Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3212
Csatlakozott: 2008. augusztus 29. péntek, 6:00
Tartózkodási hely: Újkígyós

Re: Extern használata

HozzászólásSzerző: kapu48 » 2017. június 20. kedd, 15:12

Figyelj már!

Tartsál valami ésszerű sorrendet a tanulásban!
Még a C.-t-sem ismered! Ne ugrálj már a Cpp-be!

Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00
Tartózkodási hely: Budapest

Re: Extern használata

HozzászólásSzerző: SzLacus » 2017. június 20. kedd, 17:45

Az ésszerű sorrend, hogy amibe belebotlom? :-)
Még nem fogtam fel, hogy a C és a C++ közt mi a pontos különbség, azon kívül, hogy a ++ eszi a C dolgait, és azon felül ad még lehetőségeket.
De hogy vissza kanyarodjak az extern-re, arra rádöbbentem, hogy csak fájlok között működik, és nem fogom megúszni a használatát, amint több fájlra akarom bontani a programomat. Ennek vizsgálgatása során, hamar visszajutottam oda, amit kapu48 az elején már megírt, amikor az én két árva .h fájlomhoz egy .c-be betolta amit kell. Csak ott sem fogtam fel akkor a lényeget, pedig a szemem előtt volt. Úgy is mondhatnám, hogy olvastam, csak nem értettem mit is olvasok. Mint ahogyan azt sem értettem, hogy a definiciok.h-t miért tolta be mindenhova, de most úgy gondolom hogy értem.
Majd amikor újra böszmét kérdezek, kiderül, hogy még nem minden ősszefüggését értem. :-)
Addig is köszönet az okosításért mindenkinek.

Avatar
csabeszq
Bitfaragó
Hozzászólások: 660
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: Extern használata

HozzászólásSzerző: csabeszq » 2017. június 25. vasárnap, 16:52

Még nem fogtam fel, hogy a C és a C++ közt mi a pontos különbség, azon kívül, hogy a ++ eszi a C dolgait,


Erre akart kapu48 rávilágítani. A C/C++ közti különbség kb. akkora, mint a robogó és a BMW között. Mindkettővel lehet közúton közlekedni, ergo ugyanaz. :D
Mellesleg az sem igaz, hogy a C++ megeszi a C-t. Nagyon sok esetben nem eszi meg a C-s kódot.

A library fájlokat meg egyelőre ne nézegesd, mert nem vagy azon a szinten. Lehet csűrni, csavarni, csak semmi értelme nincs. Próbálj a C-re koncentrálni és példaprogramokat nézegess library fájlok helyett. A tavir-os olvasók 99%-ának fogalma nincs róla, hogy működnek a library fájlok. Weak referenciától ABI-n át AVR-GCC specifikus cuccokon át mindent tartalmaznak.

Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00
Tartózkodási hely: Budapest

Re: Extern használata

HozzászólásSzerző: SzLacus » 2017. június 25. vasárnap, 18:50

Azon igyekszem, hogy a fájlokra bontott program írás alapjait valahogyan elkapjam. Ennek kapcsán került látómezőbe az extern, ami ennek a topiknak a nyitására sarkallt. Kapu48 által többször linkelt könyv igen tömören szól a fájlokra bontásról, és azt nem nagyon magyarázza el, hogy amit példaként felrajzol, ott mi miért kerül oda, ahova. Ezért aztán keresgél kutat az ember, még könyvtárakba is bele-bele kukucskál, hátha ott elkapja a fonalat, és megérti a fájlokra bontás logikáját, szabályait.
Nem lettem okosabb a könyvtárak nézegetésétől, úgy hogy nem ez lesz a megértés kulcsa.
Még nem találtam meg azt a magyar nyelvű leírást, könyvet egyetemi jegyzetet, stb, ami rávezetett volna a megoldásra. Az sem segít, hogy egy igen terjedelmes, sok eljárást tartalmazó programomat szeretném értelmes darabokra bontva kezelhetőbbé tenni, így ha valamelyik rész kirakom, akkor rögtön fordítási hiba jön, amiről el kell döntenem, hogy hol a hiba. Haladgat a dolog, fogy a nagy spagetti, és kisebb kupacok jönnek létre. Most azon akadtam el, hogy például az lcd-hez kapcsolódó eljárásokat kirakva külön állományba, hova kell tenni az "LiquidCrystal_I2C lcd((PCF8574 | LCDPCFCIM),4,5,6,0,1,2,3,7,NEGATIVE);" sort. Persze elég sok eljárásomban szerepel lcd. kezdetű hívás, és amíg az mind jó helyre nem kerül, addig mindíg hibára fogok futni.
Szóval köszönöm a segítséget, nem akarok én a könyvtárban turkálni, attól még nagyon messze vagyok. Szeretnék viszont olyan kódot írni, amilyet majd később is hajlandó leszek visszaolvasni, mert érthető könnyen olvasható.


Vissza: “Arduino / C-nyelvű programozás (AVR-Duino, EthDuino, Arduino, Diecimila)”

Ki van itt

Jelenlévő fórumozók: nincs regisztrált felhasználó valamint 5 vendég