Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Monta cpp-tiedostoa

Sivun loppuun

JoreSoft [30.12.2007 12:40:10]

#

Moiii =)
Teen tuossa pitkästä aikaa taas Visual c++:lla ohjelmaa (DLL), ja tuli sellanen ongelma matkaan, että käytän siinä SDL-komentoja, ja haluaisin laittaa sen omaan SDL_Funktiot.cpp ja SDL_Funktiot.h tiedostoihin.
Kuinka saan pääohjelman tajuamaan monta erillistä .cpp tiedostoa?
kaiketi se on mahdollista? eihän ole järkeä kerätä kaikkia 2000 funktiota samaan filuun =)
kokeilin liittää sen H-filun kautta
#include "SDL_Funktiot.h", mutta sitä pääohjelma ei osaa tajuta.
Ei myöskään, vaikka lisään pääohjelman .def, osaan ne SDL-funktioiden nimet.
C++ oppaissa, koodivinkeissä, kaikki on ympätty yhteen filuun, joten niistä ei löytynyt apua. Ei liioin gookelilla.

ville-v [30.12.2007 13:11:26]

#

Laita funktioiden määritykset h-tiedostoon kuten teitkin, ja includeta se joka tiedostossa jossa kutsut funktioita.

Itse funktiot taas laitat näihin cpp-tiedostoihin, kuten varmaankin jo teit. Nämä tiedostot on taas jostakin projektin/kääntäjän/vastaavan asetuksista liitettävä projektiin. Tällöin kaikki tiedostot käännetään kääntäessäsi ohjelman.

JoreSoft [30.12.2007 14:14:39]

#

En saanut toimimaan, kuten olisin halunnut...
Funktiot.cpp

#include "stdafx.h"

#include <windows.h>
#include <string>
#include "SDL.h"   /* All SDL App's need this */

#include "Funktiot.h"
#include "SDL_Funktiot.h"	//Liitetään erillinen SDL_Funktiot.cpp
using namespace std;

SDL_Funktiot.cpp

#include "stdafx.h"
#include "SDL.h"   /* All SDL App's need this */
#include "Funktiot.h"
#include "SDL_Funktiot.h"	//Liitetään erillinen SDL_Funktiot.cpp

Pitääkö nuo kaksi tavallaan ristiin esitellä? siis toisilleen?
tulee hirveästi virheitä, enkä tiedä mistä alkais purkaan tuota =)

Legu [30.12.2007 14:19:16]

#

Katsohan tämä koodivinkki.

JoreSoft kirjoitti:

En saanut toimimaan, kuten olisin halunnut...

Kerro vähän tarkemmin. Mitä kääntäjä sanoo?

JoreSoft [02.01.2008 22:40:42]

#

Se ongelma on ohi, kiitos vaan =)

Olisin kysynyt, onko kellään kokemusta oman DLL-kontrollin tekemisestä
visual C++:lla? että se toimii VB 6.0 : ssa

Olen tehnyt tuossa Dll.kontrollia, ja en saanut omaa "struct" osaa tunnistumaan VB:n puolella kuten tuossa esimerkissä on.

Public Type RECT
    Left As Long
    top As Long
    Right As Long
    Bottom As Long
End Type
Public Declare Function IntersectRect Lib "user32" (lpDestRect As RECT, lpSrc1Rect As RECT, lpSrc2Rect As RECT) As Long

Putkasta löysin tuollaisen esimerkin, jossa oma struct on .H-tiedostossa, mutta sitäkään en saanut tehtyä VB:llä tunnistettavaksi

https://www.ohjelmointiputka.net/koodivinkit/25046-c-koodin-jakaminen-eri-tiedostoihin
(Mod. huom: käytähän oikeaa osoitetta.)

Kokeilin tehdä sen näin:
koe.h

#ifdef SPRITEDLL_EXPORTS
#define SPRITEDLL_API __declspec(dllexport)
struct aRECT{
    int Left, top, Right, Bottom;
};
typedef struct aRECT aRECT;
extern int Koe(aRECT kk);

#else
#define SPRITEDLL_API __declspec(dllimport)
#endif

koe.cpp
int Koe(aRECT kk){return 100;}

VB:ssä

Public Type aRECT
    Left As Long
    top As Long
    Right As Long
    Bottom As Long
End Type
Public Declare Function Koe Lib "SpriteDLL.DLL" _
(kk As aRECT) As Long

Herjaa, ettei löydä Koe-osaa dll tiedostosta

Metabolix [02.01.2008 23:18:52]

#

Kuten koodivinkissä sanotaan, C++-koodissa pitää laittaa extern "C" kaikkien DLL:stä tarjottavien funktioiden eteen (sekä koodissa että otsikkotiedostoissa). On mahdollista myös merkitä koko tiedosto samalla kertaa.

extern "C" int funktio(...) {...}
extern "C" int toinen_funktio(...) {...}
extern "C" {
  // kaikki koodi;
  int funktio(...) {...}
  int toinen_funktio(...) {...}
}

Tämä vaatimus johtuu C++:n mahdollisuudesta ylikuormittaa funktioita eli luoda monta samannimistä funktiota eri parametreilla. Käännösvaiheessa C++ muuttaa funktioiden nimiä parametrien tyyppien mukaan, jotta ylikuormitetuille funktioille tulisi eri nimet ja ne voitaisiin näin erottaa toisistaan.

JoreSoft [02.01.2008 23:25:26]

#

Moi taas =)

katsoin tuota C++ generoimaa koodia, ja siinähän on #if.. #else..#endif rakenne.
Mihin osaan tuo pitäisi siis laittaa?
ennen vai jälkeen #else:n ?

olen itse laittanut ohjelma.cpp

SPRITEDLL_API bool __stdcall SpriteToBorderCollision(int ind){
int AX, AY, AW, AH;
	AX = Sprite[ind].Pos.X;
	AY = Sprite[ind].Pos.Y;
	AW = Sprite[ind].Size.Width;
.... jne

ja ohjelma.h

SPRITEDLL_API bool __stdcall SpriteToBorderCollision(int ind);

vb

Public Declare Function SpriteToBorderCollision Lib "SpriteDLL.DLL" _
    (ByVal i As Long) As Boolean

näin Dll on toiminut hyvin, vain tuo struct ei ole toiminut =)

eikös se niin ollut että C++ int on VB:n Long ??
ja short = integer ??

Metabolix [03.01.2008 16:06:49]

#

Formaatista pitää päästä yksimielisyyteen. Sellaisenaan (ilman osoitinta) siirrettävien arvojen pitää olla VB:ssä ByVal. Sen sijaan C++:n osoitin vaatii VB:ssä ByRef-avainsanan. Mahtaako ByRef olla VB:n oletusarvoinen tai jopa ainoa tapa siirtää isompia rakenteita?

JoreSoft [03.01.2008 20:08:11]

#

Juu samaan tuloksen olen päässyt, ja sain toimiin struct-luokatkin.
vb:ssä voin nyt viitata niihin, kunhan muuttuja määrittelu on sama.
ja ei tarvi sitä Byref , joten sen täytyy olla oletus.
kun löytäis vielä taulukon, missä vertaillaan c++ ja vb:n muuttujatyypit, yhteensopivuuden takia.
Kiitos avusta meta =)

- jore -

Cc [08.01.2008 15:36:07]

#

Miten saan globaalit muuttujat, joita tarvitsen esimerkiksi main.cpp ja funktiot.cpp toimimaan molemmissa, jotta voin kummastakin käyttää niitä?

Pekka Karjalainen [08.01.2008 16:37:01]

#

Kovin paljon globaaleja muuttujia ei kannata käyttää, mutta aina joskus ne ovat kelvollinen ratkaisu. Silloin kun haluat jakaa niitä eri tiedostoissa olevan koodin välillä, käytät extern-sanalla esiteltyjä muuttujia, jotka sitten on myös oikeassa paikassa määritelty. Nimen saat näkyviin eri paikkoihin header-tiedostojen ja nimiavaruuksien avulla.

Nimiavaruudet voi toki jättää pois lyhyistä ohjelmista, mutta ne kuuluvat hyvään C++-tyyliin. Lisäksi sopivilla using-lausekkeilla voi vähentää kohtuutonta :-merkkien kirjoitusta. Yleensä on kuitenkin hyvä idea kertoa ohjelman lukijalle, mistä ne viitatut asiat milloinkin tulevat.

Tässä on minimaalinen esimerkki externinä omassa nimiavaruudessaan esitellyn muuttujan käytöstä suoraan, sekä funktion kutsumisesta samasta nimiavaruudesta. Esittely on tiedostossa moduuli.hpp, joka tuossa onkin ekana.

//moduuli.hpp
namespace moduuli {
	extern int x;
	extern void kasvata (int);
}
// main.cpp
#include <iostream>
#include "moduuli.hpp"

int main () {
	std::cout << "eka: "  << moduuli::x << std::endl;
	moduuli::x = 3;
	std::cout << "toka: " << moduuli::x << std::endl;
	moduuli::kasvata( 5 );
	std::cout << "vipa: "<< moduuli::x << std::endl;
}
// moduuli.cpp
#include "moduuli.hpp"

namespace moduuli {

	int x = 1; // saa alkuarvon tässä

	void kasvata (int paljonko) {
		x += paljonko;
	}

}

Ehkä on viisaampaa, ettei yleisesti sisennä koodia namespace/nimiavaruus-blokkien sisällä, koska se aiheuttaa vain vaivaa normaalipituisten rivien kanssa. Sulkevan aaltosulun voi kommentoida, jotta tietää minkä pari se on.

Tämä käännän yksinkertaisesti komennolla g++ -Wall *.cpp, vaikka tietenkin omassa ohjelmassasi käytät make-ohjelmaa tai esim. jonkin IDEn projektisysteemiä. Tulostus on yllänäkyvät tekstit, sekä luvut 1, 3 ja 8, kuten sopii olettaa.

Metabolix [08.01.2008 17:48:14]

#

Cc kirjoitti:

Miten saan globaalit muuttujat toimimaan molemmissa?

Tämäkin kerrotaan tuossa aiemmin mainitussa koodivinkissä. Mutta hyvä, että kysyit, kävin nimittäin selventämässä asiaa vielä hieman. :)


Sivun alkuun

Vastaus

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

Tietoa sivustosta