Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Oma .h-tiedosto

Sivun loppuun

KoodiNoppa [13.09.2007 22:19:00]

#

Miten saan tehtyä oman .h-tiedoston? Tiedostoon pitäisi saada funktioita, jotka käyttävät SDL:n ominaisuuksia ja mahdollisesti alustettua joitakin arvoja.

Legu [13.09.2007 22:31:57]

#

Näin se kannattanee tehdä:

/* oma.h */
#ifndef _OMA_H
#define _OMA_H

const int vakio = 123;
void SanoMoi();

#endif
/* oma.cpp */
#include <iostream>
#include "oma.h"

void SanoMoi()
{
    std::cout << "Moi " << vakio << std::endl;
}
/* main.cpp */
/* vakio on myös täällä main.cpp:ssä tiedossa */
#include "oma.h"

int main()
{
    SanoMoi();
    return 0;
}

Ja sitten pitää muistaa antaa kääntäjälle nuo molemmat tiedostot, main.cpp ja oma.cpp.
g++:lla kyseisen ohjelman kääntäminen onnistuu siis näin:

g++ main.cpp oma.cpp -o ohjelma

KoodiNoppa [13.09.2007 23:22:05]

#

Esimerkki toimii täydellisesti, mutta omassa viritelmässäni jokin mättää. Onko sillä mitään vaikutusta koodin toimivuuteen, että .h-tiedosto sisältää SDL:n tyyppejä (SDL_Surface) ja/tai .cpp:ssä funktiot käyttävät toisiaan?

Hmm...Kun käännän sitä .cpp-tiedostoa, jokainen SDL_Surfacea käyttävä funktio on kuulemma valmiiksi määritelty...
"in function 'SDL_Surface* CLS(SDL_Surface*,int)'
redefinition of 'SDL_Surface* CLS(SDL_Surface*,int)'
'SDL_Surface* CLS(SDL_Surface*, int)' previously defined here"
#include "sdl/sdl.h" ja #include "oma.h" ovat tiedostossa.
Onko jokin unohtunut?

Tässä vielä tuo CLS-funktio (on niitä muitakin, mutta tässä yksi):

SDL_Surface* CLS(SDL_Surface *scr,int col){
int ul;
    for(ul=0;ul<SCREEN_WIDTH*SCREEN_HEIGHT;ul++)
    {
         ((unsigned int*)scr->pixels)[ul]=col;
    }
    return scr;
}

SCREEN_WIDTH ja SCREEN_HEIGHT on oma.h:ssa alustettuja.

EDIT: unohdin sanoa, että oma.h:ta käännettäessä tulee
"[build error] no rule to make target 'tiedosto.o' stop."

Metabolix [13.09.2007 23:40:50]

#

Teinpä tuosta koodivinkin, jos vaikka saisit siitäkin selvää. Vilkaise vielä siitä, että olet tehnyt oikein.

Blaze [13.09.2007 23:41:18]

#

KoodiNoppa kirjoitti:

Tässä vielä tuo CLS-funktio (on niitä muitakin, mutta tässä yksi):

Nopeampi versio:

SDL_FillRect(scr, NULL, col);

KoodiNoppa [14.09.2007 00:33:05]

#

Korjasin koodia koodivinkin mukaan, mutta edelleen tulee se "[build error] no rule to make target 'tiedosto.o' stop" kun kääntää .h:ta. cpp kääntyy vaivattomasti. Kokeilin kaikkia funktioita ja muuttujia externillä ja ilman, sama tulos kaikilla. Myös funktioiden pitäisi olla samat (siis samat paluuarvon tyypit, parametrien tyypit ja määrät...)

p.s. Nyt on FillRect käytössä :)

Metabolix [14.09.2007 08:55:31]

#

Ei .h:ta kuulu kääntää, se on vain includea varten.

KoodiNoppa [14.09.2007 14:56:54]

#

Mitenkäs liitän (=linkitän?) ne tiedostot projektiin? Dev-c++ on käytössä.

os [14.09.2007 15:48:04]

#

include on englantia ja tarkoittaa sisällyttämistä. Esikääntäjä liittää tällä komennolla koko .h (tai .hpp) -tiedoston sisällön sille riville, jolla include-komento on. Sama kuin kirjoittaisit tai kopioisit koko tiedoston sisällön itse tähän kohtaan. .h -tiedostoja ei välttämättä tarvitse liittää esimerkiksi Dev-C++:n projektiin eikä niitä myöskään käännetä tai "linkitetä" erikseen.

Pekka Karjalainen [14.09.2007 16:40:53]

#

H-tiedostot tulevat automaattisesti mukaan, jos ne ovat oikeissa hakemistoissa (isossa projektissa #include-viittaukseen voi laittaa alihakemistoja). Voi ne tietenkin liittää tiedostoluetteloon projektissa, ja se on varmasti hyvä idea IDE:n käyttäjälle. En osaa neuvoa tarkasti Dev-C++:n kohdalla kuitenkaan.

Asia on jo selitetty hyvin, mutta voisin vielä lisätä esimerkin. Tämä on ajettu MinGW:llä ja optiot ovat GCC-kohtaisia. Esim. MS:n kääntäjällä on omat tavat. Huomiota sopii kiinnittää siihenkin, että en koskaan käännöskomennossa mainitse testi.h-tiedoston nimeä, vaan se todella tulee ns. itsestään mukaan.

Minulla on tiedostot testi.h ja testi.c samassa hakemistossa.

/* Tämä on testi.h-tiedosto. Katoaako kommentti? */

extern char* msg;
#include "testi.h"

char* msg= "Tämä taas on testi.c-tiedosto.";

Nyt voin katsoa, mitä esikäsittelijä tekee, jos käytän optiota -E. Se kertoo, että tehdään vain esikäsittylevaihe, eikä yritetä kääntää mitään.

C:\temp>gcc -E testi.c
# 1 "testi.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "testi.c"
# 1 "testi.h" 1


extern char* msg;
# 2 "testi.c" 2

char* msg= "Tämä taas on testi.c-tiedosto.";

Tältä se näyttää GCC:llä. Huom: tässä on ensimmäinen komentorivi ja siitä seuraava tulostus, eli tulos on yksi tiedosto, joka nyt vain näkyy tulosteena. Esitys ei ole erityisesti suunniteltu ihmisten luettavaksi, siitä vain voi tarkistaa, mitä oikeastaan tapahtui.

On myös hyödyllinen -P-optio, joka ei jätä kääntäjän omia tietoja tulostettuun tiedostoon.

C:\temp>gcc -E -P testi.c
extern char* msg;


char* msg= "Tämä taas on testi.c-tiedosto.";

Taas on komentorivi & tulostus. Ja nyt näkyy selvästi, että esikäsittelijä poistaa jo kommentit, koska nehän eivät kääntäjää kiinnosta, mutta muuten tiedostojen sisältö on aika uskollisesti toistettu.

Tästä voikin päätellä, että esikääntäjää voi käyttää hyvin yksinkertaisiin tiedostonmuokkauksiin, kunhan ei ylläty katoavista kommenteista. Sen käsittelemän tekstin ei nimittäin tarvitse olla laillista C- tai C++-kieltä ollenkaan. Varsinaiseen tekstinprosessointiin kannattaa mielestäni kuitenkin käyttää sopivaa kieltä, eikä hakkeroida tällä tavalla.

Pointti oli siis se, että se kääntäjä kyllä voi kertoa, mitä se tekee, jos siltä kysyy. Normaali kääntötoiminto pitää sisällään useita vaiheita, mutta näitä välitilanteita ei tarvitse koskaan nähdä, jos ei halua.

KoodiNoppa [14.09.2007 18:46:47]

#

Joko kysyin huonosti tai olen taas hidas tajuamaan asioita...
Kun koodi käännetään konsolissa, gcc:lle annetaan tarvittujen tiedostojen nimet. Mihin nimet laitetaan, jota Dev-c++ osaisi lähettää ne kääntäjälle? Vai lisääkö Dev-C++ ne itse?

Millä tavalla käännetty ohjelma voisi liittää itseensä koodia? Eli jos ohjelmasta poistuu ja muuttaa koodi.h:ta, ohjelma ei olisi enää sama.

Metabolix [14.09.2007 22:27:37]

#

Jossakin kohti (oletuksena kai vasemmassa reunassa) on lista tiedostoista, jotka kuuluvat projektiin. Tämän listan saa varmasti auki jostain valikosta, mahdollinen nimi olisi "files in project" tai jokin vastaava. Siihen listaan voit hilata tiedostosi. Tietenkin jos luot tiedostot alusta asti Dev-C++:lla, ne kai yleensä tulevat jopa automaattisesti mukaan avoimeen projektiin.

KoodiNoppa [14.09.2007 23:02:13]

#

Ei toimi (ne on muuten ollu siellä reunassa koko ajan, ilman mitään kunnon syytä...). Liian monimutkaista... ilmeisesti pitää odotaa jonkin aikaa ja yrittää uudestaan saada asiasta selvää, se yleensä toimii.

Tuli mieleen kysymys: miten esim. stdlib toimii pelkällä #includella?

Metabolix [14.09.2007 23:12:16]

#

Kääntäjä yleensä linkittää ihan automaattisesti ne valmiiksi käännetyt osat kielen peruskirjastoista, siis esimerkiksi juuri stdlib- ja stdio-funktiot. Yleensä myös matematiikkafunktiot (math.h) tulevat samassa paketissa, mutta toisinaan pitää kääntäjälle (tai linkkerille) antaa parametri -lm, missä -l tarkoittaa linkittämistä ja m merkitsee matematiikkakirjastoa. Omastakin koodistaan voi tehdä kirjaston, joka toimii includella ja linkittämisellä (-lkirjasto), mutta siitä touhusta saat ottaa itse selvää, jos on ihan pakko. Eipä tuota mahdollisuutta ole itse tarvinnut käyttää (paitsi valmiita kirjastoja kääntäessä).


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta