Nejasnost include XC8

Ahoj,

prohlížím si cizí projekt a mám nejasnost ohledně příkazu include.

V hlavním programu volá #include “DS1302.h”

kde jsou nějaké definice proměnných a potom volá funkce které jsou zapsané v DS1302.c ale tento soubor už nikde volaný není.
Je to tak, že když se zavolá .h tak se automaticky načte i .c?

Já si napsal jeden podprogram a celý ho mám jen v .h, je to špatně?

Cau, nektery kompilatory to tak asi maj ze si nactou *.c prislusnyho *.h
to *.c neni nahodou vlozeny do toho *.h ?
uz sme to tu resily s piityy , ale nemuuuzu to najit

Právě že ne.

v .c je
#include <htc.h>
#define _XTAL_FREQ 4000000UL
#include “DS1302.h”

ale v tom .h ani jinde v projektu odkaz na .c neni

Ono je to vesměs jedno. Co jsem si udělal knihovnu pro obsluhu LCD tak jsem vše napsal do .h
Jen mě to zaujmulo.
Tady je komplet program, který skoumám ebastlirna.cz/modules.php?na … d&id=29124

aaa nasel :wink: viewtopic.php?t=911&postdays=0&postorder=asc&start=120

Tak jsem to trošku prostudoval a snažil se svojí knihovnu pro obsluhu LCD předělat tak jak by to mělo být, ale nejde mi zkompilovat.

Pořád to píše
:0: error: undefined symbols:
_lcd_move(dist/default/production\Test.production.obj) _lcd_init(dist/default/production\Test.production.obj) _lcd_clear(dist/default/production\Test.production.obj) _lcd_zapis(dist/default/production\Test.production.obj)
(908) exit status = 1
Test.zip (73.3 KB)

Mám obavu, že si budeš muset přečíst něco o Cčku. V *.c souborech jsou uloženy funkce, v souborech *.h jsou jenom funkční prototypy. Jinými slovy v *.h jsou uvedeny názvy funkcí s jejich parametry, aby překladač věděl, jak zkompilovat soubory, ze kterých jsou funkce volány a ukládá informace pro linker, které funkce jsou volány. V *.c je kód těch funkcí. Ty po překladu bere linker, který z informací od překladače pak spojí všechny dílčí objekty do jednoho kompletního programu. Pokud tedy nacpeš veškerý kód do jednoho *.h souboru a tento *.h soubor vložíš do dílčích *.c programů (k čemuž *.h soubory slouží), tak Ti to zaručeně nepůjde přeložit.

Do každého souboru, ve kterém používáš funkce ze souboru název.c musíš vložit hlavičkový soubor název.h.

Já jsem to právě tak udělal. Do .h jsem dal definice a v .c je jen program. Ale teď mi to kupodivu nejde.
Když jsem měl vše špatně v .h tak mi to šlo :smiley:

me to taky nefunguje :laughing: ,uz to neresim, napisu to vsechno do novyho *.c a to si tam pak vlozim a je to …

Děkuji za vytáhnutí tématu, taky jsem řešil jak rozjet externí “knihovny” v C30 pro dsPIC.
A už mi to chodí! Tak to sem napíšu, kdyby to náhodou někdo hledal pro C30.

Tohle stačí dát do main.c

#include "MCUInit.h"

Definice funkcí v hlavičkovém souboru MCUInit.h

#ifndef     _MCUInit_H_
#define    _MCUInit_H_

    extern void NeznamaFunkce (void);

#endif

V MCUInit.c už jen stačí napsat samotnou funkci

#include "MCUInit.h"

//------------------------------------------------
void NeznamaFunkce(void) //Funkce jen zabije chvilku casu
{
       __builtin_nop();
       __builtin_nop();
}

Ono je to právě nelogické, protože se ten .h soubor s prototypem funkce připojuje jak do hlavního .c souboru, tak do .c souboru kde je funkce definována, a přitom ten soubor s prototypem v podstatě “nic důležitého” neobsahuje… začíná se jakoby od prostředka. Nicméně když je to tak v definici C language, bude asi potřeba si na to zvyknout.

Ono je to trošku jinak. Prototypy funkcí můžeš mít klidně v *.c souboru na začátku. Jenže pokud funkci používáš i v jiném *.c souboru, musel bys prototyp té funkce psát v každém souboru, kde ji používáš. Proto se prototypy definují v *.h souboru a ten se pomocí include vkládá do všech *.c souborů, kde ty funkce používáš. Napšeš program :

[code]void funkce1(void)
{
char a=funkce2();
}

char funkce2(void)
{
return 7;
}
[/code]

Při překladu Ti to na řádce char a=funkce2(); bude psát, že funkce2 není definována. Je to proto, že překladač jí ještě nepřeložil, tudíž o ní neví. Proto existují prototypy funkcí napsané buď na začátku *.c souboru (pokud funkce z tohoto souboru nepoužíváš v žádné jiné části programu) nebo *.h souboru a vloženém do *.c souboru pomocí include. Překladač na začátku dostane prototypy funkcí (dozví se, že někde se bude takováto funkce vytvářet) a při překladu pak už nezáleží na tom v jakém pořadí jsou kódy jednotlivých funkcí v souboru zapsány. Na druhou stranu pokud se spleteš a necháš v programu jenom prototypy funkcí (do projektu vložíš *.h soubory, ale zapomeneš na příslušný *.c nebo *.lib soubor), Ti sice program půjde přeložit, ale linker skončí chybou, že nenašel příslušné funkce.

Jednoduše řečeno, překladač překládá soubor tak, jak ho čte a neprohledává ho dopředu. Pokud bys napsal :

[code]char funkce2(void)
{
return 7;
}

void funkce1(void)
{
char a=funkce2();
}
[/code]

pak překlad projde v pohodě i bez funkčních prototypů.

Jenže když si píšeš třeba funkce pro ovládání LCD displeje, tak chceš, abys je příště jenom vzal, vložil do projektu a všechno fungovalo. Proto píšeš funkce do zvláštního *.c souboru a do *.h souboru napíšeš funkční prototypy, případně konfiguraci pinů, kam máš displej připojený a pokud jsi šikovný, tak i způsob, jakým s displejem komunikuješ (v *.c souboru musí být použitý podmíněný překlad podle nastavení z *.h souboru) atd.

Tudíž pro kolemjdoucího : *.h soubor právě obsahuje důležité informace pro překladač, aby věděl, že někde existuje určitá funkce s určitými parametry, aby při překladu volání této funkce přeložil správně její volání (předávání parametrů apod.) i když funkci samotnou ještě nepřekládal nebo překládal v jiném souboru.

Jinak slovíčko “extern” nemá v *.h souboru co dělat, pokud je funkce součástí překladu nebo vkládané knihovny.

Jj, já se nehádám, jen jsem konstatoval že z pohledu začátečníka v C to vypadá trochu divně (obzvlášť pokud už jsou zkušenosti z něčeho odlišného). Nicméně bude to asi fakt jen o zvyku.

OK. Berte to jako vysvětlení, proč se tak děje. Začátečník (a hlavně samouk) většinou zjistí, že se něco nějak dělá a ve většině případů se nedozví proč. Tohle, co jsem psal, jsme se učili na škole a je to podle specifikací Cčka. To, že třeba WinAVR program přeloží a jenom napíše warning, že funkce ještě nebyla definována, je vlastně jenom nedodržení specifikací při překladu. Pokud by se překladač držel specifikace, by toto skončilo chybou při překladu úplně stejně, jako když se použije proměnná bez deklarace.