|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 16.03.2004, 18:09 Titel: Fehler beim aufteilen eines Programms in Module |
|
|
Ich hab gerade die Direct 3D Klasse aus dem 19 Kapitel geschrieben. Nun wollte ich den Quellcode in Module aufteilen, und zwar:
CDirect3D.cpp //Die Direct3D Klasse
DirectXGraphics.cpp //Die main Funktion usw.
global.h //da wird die Bildschirmgröße definiert.
Das einbinden mit der Global.h funktioniert. Im Moment habe ich die D3D Kallse vor der main funktion, da von ihr ja ein globales Objekt angelegt wird, welches ich in der main Funktion nutze.
Damit es besser verständlich wird, zeig ich mal den Code:
Code: |
/* Bibliotheken:
dxguid.lib d3d9.lib d3dx9.lib */
// Headerdatei
#include "global.h"
#include <d3d9.h>
#include <d3dx9.h>
#include <stdio.h>
void Error(char Text[]);
class CDirect3D
{
public:
CDirect3D();//Konstruktor
virtual ~CDirect3D();//Destruktor
bool Init(HWND hWnd, bool bWindowed=true);
void SetClearColor(D3DCOLOR Color);
void DrawText(LPCSTR Text, int x, int y, D3DCOLOR TextColor);
void BeginScene(void);
void EndScene(void);
protected:
void CreateFont(void);
void CleanUp(void);
LPDIRECT3D9 lpD3D;//Das Direct3D Objekt
LPDIRECT3DDEVICE9 lpD3DDevice;// Zeiger auf das Direct3D-Device
LPD3DXFONT lpD3DFont; //Direct3D Font für Texte
D3DCOLOR m_ClearColor;
};
bool CDirect3D::Init(HWND hWnd, bool bWindowed)
{
D3DPRESENT_PARAMETERS PParams;
lpD3D=Direct3DCreate9(D3D_SDK_VERSION);
if(NULL==lpD3D)
{
Error("D3D Objekt konnte nicht erzeugt werden!");
return false;
}
ZeroMemory(&PParams, sizeof(PParams));
PParams.SwapEffect =D3DSWAPEFFECT_DISCARD;
PParams.hDeviceWindow =hWnd;
PParams.Windowed =bWindowed;
PParams.BackBufferWidth=SCR_WIDTH;//Auflösung und Farbtiefe
PParams.BackBufferHeight=SCR_HEIGHT;
PParams.BackBufferFormat=D3DFMT_A8R8G8B8;
if(FAILED(lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &PParams, &lpD3DDevice)))
{
Error("Gerät konnte nicht angelegt werden!");
return false;
}
CreateFont();
return true;
}
void CDirect3D::CreateFont(void)
{
LOGFONT LogFont={0};
strcpy(LogFont.lfFaceName, "Arial");
if(FAILED(D3DXCreateFontIndirect(lpD3DDevice, &LogFont, &lpD3DFont)))
{
Error("Font konnte nicht erzeugt werden");
}
}
void CDirect3D::CleanUp(void)
{
if(NULL!=lpD3DDevice)//Direct3D Device freigeben
{
lpD3DDevice->Release();
lpD3DDevice=NULL;
}
if(NULL!=lpD3D)//Direct3D Objekt freigeben
{
lpD3D->Release();
lpD3D=NULL;
}
}
void CDirect3D::BeginScene(void)
{
lpD3DDevice->Clear(0, 0, D3DCLEAR_TARGET, m_ClearColor, 0, 0);
lpD3DDevice->BeginScene();
}
void CDirect3D::EndScene(void)
{
lpD3DDevice->EndScene();
lpD3DDevice->Present(0, 0, 0, 0);
}
CDirect3D::CDirect3D()
{
lpD3D = NULL;
lpD3DDevice = NULL;
lpD3DFont = NULL;
}
CDirect3D::~CDirect3D()
{
CleanUp();
}
void CDirect3D::SetClearColor(D3DCOLOR Color)// Farbe für den Backbuffer festlegen
{
m_ClearColor = Color;
}
void CDirect3D::DrawText(LPCSTR Text, int x, int y, D3DCOLOR TextColor)// Text an Position x,y ausgeben
{
RECT r = { x, y, 0, 0 };
lpD3DFont->DrawText(Text, -1, &r, DT_CALCRECT, TextColor);// Größe des Rechtecks berechnen
lpD3DFont->DrawText(Text, -1, &r, DT_CENTER, TextColor); // Text ausgeben
}
//Funktionsprototypen
HWND CreateMainWindow(HINSTANCE hInstance);
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
//Globale Variablen
HWND hWnd = 0;// Das Fensterhandle
CDirect3D Direct3D;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) // Windows main-Funktion
{
MSG msg;// Struktur, in der Informationen zur Nachricht gespeichert werden
hWnd=CreateMainWindow(hInstance);// Fenster erzeugen und Handle speichern
if(NULL==hWnd)// Wenn der Rückgabewert 0 ist, ist ein Fehler aufgetreten
{
Error("Fenster konnte nicht erzeugt werden");
return -1;
}
if(!Direct3D.Init(hWnd, false))
{
Error("InitDirect3D fehlgeschlagen");
return -1;
}
Direct3D.SetClearColor(0xff0000ff);
// Diese Schleife läuft bis die Nachricht WM_QUIT empfangen wird
while(GetMessage(&msg,NULL,0,0))
{
// Nachricht an die Callbackfunktion senden
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;// Rückgabewert an Windows
}
// Fenster erzeugen
HWND CreateMainWindow(HINSTANCE hInstance)
{
WNDCLASSEX wndClass =
{
sizeof(WNDCLASSEX), // Größe angeben
CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, // Standardstile
MessageHandler, // Callback-Funktion
0, // Zusätzliche Angaben
0, // nicht benötigt
hInstance, // Anwendungsinstanz
LoadIcon(NULL, IDI_WINLOGO), // Windows-Logo
LoadCursor(NULL, IDC_ARROW), // Normaler Cursor
(HBRUSH)GetStockObject(WHITE_BRUSH), // Weißer Pinsel
NULL, // kein Menü
"WindowClass", // Der Name der Klasse
LoadIcon(NULL, IDI_WINLOGO) // Windows Logo
};
RegisterClassEx(&wndClass);
return CreateWindowEx(NULL, // Keine erweiterten Stile nutzen
"WindowClass", // Klassenname
"DX9 Game", // Fenstertitel
WS_OVERLAPPEDWINDOW | // Fenster
WS_VISIBLE, // Eigenschaften
0, 0, SCR_WIDTH, SCR_HEIGHT, // Anfangsposition und Größe
NULL, // Handle des Elternfensters
NULL, // Handle des Menüs
hInstance, // Anwendungsinstanz
NULL); // wird nicht benötigt
}
// Diese Funktion wird von Windows aufgrufen, wenn eine Nachricht
// für Ihr Programm vorliegt
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
D3DCOLOR ClearColor=D3DCOLOR_XRGB(0, 0, 255);//blau
D3DCOLOR TextColor=D3DCOLOR_XRGB(255, 0, 0);//rot
RECT r={100, 100, 0, 0};
switch(msg)// testen, um welche Nachticht es sich handelt
{
// wenn das Fenster geschlossen wird, eine Nachricht senden,
// die das Programm beendet
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
DestroyWindow(hWnd);
break;
}
break;
case WM_PAINT:
Direct3D.BeginScene();
Direct3D.DrawText("C3-Soft ist voll cool", 100, 100, 0xffff0000);
Direct3D.EndScene();
break;
}
// Wenn wir uns nicht um die Nachricht gekümmert haben
// wird sie an die Standardnachrichtenverarbeitung von Windows
// geschickt
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void Error(char Text[])
{
FILE *Datei;
Datei=fopen("Error.txt", "a");
fprintf(Datei, "%s\n", Text);
fclose(Datei);
} |
nun wollte ich den ganze CDirect3D Klasse in eine eigene Datei schreiben:
Code: |
/* Bibliotheken:
dxguid.lib d3d9.lib d3dx9.lib */
// Headerdatei
#include "global.h"
#include <d3d9.h>
#include <d3dx9.h>
#include <stdio.h>
void Error(char Text[]);
#include "CDirect3D.cpp"
//Funktionsprototypen
HWND CreateMainWindow(HINSTANCE hInstance);
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
//Globale Variablen
HWND hWnd = 0;// Das Fensterhandle
CDirect3D Direct3D;
//und so weiter
|
Also genau das selbe wie oben. Jetzt findet er aber beim kompilieren die ganzen Ausdrücke nicht.
Code: | Kompilierung läuft...
CDirect3D.cpp
F:\C++\DirectXGraphics\CDirect3D.cpp(7) : error C2061: Syntaxfehler : Bezeichner 'HWND' |
insgesamt sind es 58 Syntaxfehler!
Also müssen die #include Dateien auch in die CDirect3D.cpp:
Dann bekomme ich aber 10 Linkerfhler:
Code: |
--------------------Konfiguration: DirectXGraphics - Win32 Debug--------------------
Kompilierung läuft...
CDirect3D.cpp
Ueberspringen... (keine relevanten Aenderungen gefunden)
DirectXGraphics.cpp
Linker-Vorgang läuft...
DirectXGraphics.obj : error LNK2005: "public: bool __thiscall CDirect3D::Init(struct HWND__ *,bool)" (?Init@CDirect3D@@QAE_NPAUHWND__@@_N@Z) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "protected: void __thiscall CDirect3D::CreateFontA(void)" (?CreateFontA@CDirect3D@@IAEXXZ) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "protected: void __thiscall CDirect3D::CleanUp(void)" (?CleanUp@CDirect3D@@IAEXXZ) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "public: void __thiscall CDirect3D::BeginScene(void)" (?BeginScene@CDirect3D@@QAEXXZ) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "public: void __thiscall CDirect3D::EndScene(void)" (?EndScene@CDirect3D@@QAEXXZ) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "public: __thiscall CDirect3D::CDirect3D(void)" (??0CDirect3D@@QAE@XZ) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "public: virtual __thiscall CDirect3D::~CDirect3D(void)" (??1CDirect3D@@UAE@XZ) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "public: void __thiscall CDirect3D::SetClearColor(unsigned long)" (?SetClearColor@CDirect3D@@QAEXK@Z) bereits in CDirect3D.obj definiert
DirectXGraphics.obj : error LNK2005: "public: void __thiscall CDirect3D::DrawTextA(char const *,int,int,unsigned long)" (?DrawTextA@CDirect3D@@QAEXPBDHHK@Z) bereits in CDirect3D.obj definiert
Debug/DirectXGraphics.exe : fatal error LNK1169: Ein oder mehrere mehrfach definierte Symbole gefunden
Fehler beim Ausführen von link.exe.
DirectXGraphics.exe - 10 Fehler, 0 Warnung(en) |
Ich hab irgendwo gelesen, das man sich mit #pragma once vor solchen mehrfachdefinitionen schützen kann, und hab das deshalb an den Anfang der CDirect3D.cpp geschrieben, aber es nütz nichts!
Also, wie kann ich es schaffen, das der Quellcode getrennt ist, sich aber trotzdem kompilieren lässt? _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
HotAcid Super JLI'ler
Alter: 43 Anmeldedatum: 04.08.2002 Beiträge: 372 Wohnort: Berlin Medaillen: Keine
|
Verfasst am: 16.03.2004, 18:20 Titel: |
|
|
Sie dir dochmal das Beispiel DIRECT3DCLASS an und schreib dann, was du daran nicht verstehen kannst. Da wird doch genau das gemacht, was du hier vorhast. _________________ StGB §§ 328 Abs. 2 Pkt 3:
Mit Freiheitsstrafe bis zu fünf Jahren oder mit Geldstrafe wird bestraft, wer eine nukleare Explosion verursacht. |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 16.03.2004, 18:57 Titel: |
|
|
Hab ich ja. Aber ich nutze z. B. meine eigene Error Funktion, die Fehlermeldungen in eine Textdatei schreibt, und die wird aus beiden Dateien aufgerufen. Also muss der auch in beiden Dateien einen Prototypen haben, weil er sie sonst nicht findet. Eigentlich dürfte der Fehler ja auch nicht auftreten, wenn die CDirect3D.cpp zuerst in die DirectXGraphics.cpp gescchrieben würde und dann erst kompileirt wird. Aber anscheinend versucht der Computer ja, erst die Dateien zu kompileiren und dann erst zusammen zu fügen. Gibt es nicht noch eine Möglichkeit, das zu umgehen?
Ich verstehe die Logig vom Präprozessor nicht. _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
HotAcid Super JLI'ler
Alter: 43 Anmeldedatum: 04.08.2002 Beiträge: 372 Wohnort: Berlin Medaillen: Keine
|
Verfasst am: 16.03.2004, 19:08 Titel: |
|
|
Nein, musst du nicht. Du schreibst die Error-Funktion in eine eigene Datei, die du dann in alle benötigten Dateien inkludierst. _________________ StGB §§ 328 Abs. 2 Pkt 3:
Mit Freiheitsstrafe bis zu fünf Jahren oder mit Geldstrafe wird bestraft, wer eine nukleare Explosion verursacht. |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 16.03.2004, 21:51 Titel: |
|
|
Da gibts einen ziemlich simplen Doppeleinbindungsschutz:
Code: | //Headerdatei
#ifndef _HEADERNAME_
#define _HEADERNAME_
//Headerinhalt
#endif |
So wird der Header nur ein einziges Mal definiert, aber du kannst trotzdem in verschiedene Dateien "#include "header.h" schreiben _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
Hazel JLI MVP
Alter: 39 Anmeldedatum: 19.07.2002 Beiträge: 1761
Medaillen: Keine
|
Verfasst am: 16.03.2004, 22:35 Titel: |
|
|
Code: |
..
#include "CDirect3D.cpp"
|
Was willst du denn DAMIT bezwecken?? Sowas tut man nicht, das ist unanständig. ;) _________________ *click* Dabuu!?
Twitter: http://twitter.com/Ollie_R
|
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 16.03.2004, 23:20 Titel: |
|
|
@Hazel:
Sowas nennt man dann bestimmt Freestyle
#pragma once müsste allerdings auch ausreichen. Kann ja sein das du irgendwo eine Variable oder ähnliches neu erstellt hast obwohl sie schon existiert. _________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 17.03.2004, 08:01 Titel: |
|
|
Mir ist das irgendwie zu nervig. Ich hab jetzt alles in einer Datei alles läuft prima und ich kann weiter programmieren. Wenn einer irgendwo einen Artikel kennt, wo #include genau beschriebn wird, und wie man es schafft, das er alles richtig kompileirt, kann er das ja hier schreiben.
Ist zwar voll unübersichtlich, wenn alles in eienr Datei steht, aber es funktioniert wenigstens. _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
Chewie Super JLI'ler
Anmeldedatum: 17.07.2003 Beiträge: 382
Medaillen: Keine
|
Verfasst am: 17.03.2004, 08:27 Titel: |
|
|
am einfachsten ist es wohl, wenn du in deiner global.h alle anderen header inkludierst, und in jeder .cpp machst du ein #include "global.h".
du musst nur überall die #ifndef's machen, wie der Lord beschrieben hat. |
|
Nach oben |
|
|
andijota Junior JLI'ler
Anmeldedatum: 07.11.2002 Beiträge: 66 Wohnort: Berlin Medaillen: Keine
|
Verfasst am: 17.03.2004, 10:25 Titel: |
|
|
toll, genau das gleiche problem hab ich auch noch nicht 100% ig durchschaut, eine gute sache ist dafuer das prinziep der Vorwaertsdeclaration, nehme ich an. Ich hab mir auch genervt von errors mit ner grossen datei geholfen. (5000 Zeilen ) [[die profis werden jetzt lächeln ]] Spagetti-Code wie zu frühen BASIC-Zeiten sollte man aber nicht mehr schreiben müssen..
hier werden wir für thema Vorwärtsdeclaration fuendig:
in http://zfx.info/Board.php geht die suche nicht, deshalb:
Demo von (c) AFE-GmdG (angabe hat er ausdrücklich gewünscht ), hab eine erklärende consolen-ausgabe zugefuegt:
http://home.arcor.de/andijota/Download/ThreadDemoCpp/Thr.zip
http://www.programmierer-board.de/phpBB2/index.php
..bitte schreibt mal, welche grundsaetzlichen Vorgehensweise zum Aufteilen in MODULE noetig sind um NIE-NIE-MALS doppelte symbole usw.... errors zu haben, also 1.. 2.. 3..
/*
dazu koennte noch die frage passen, was von globalen variablen und extern - declarationen zu halten ist, soll man ALLES in Klassen unterbringen?
globale Variablen werden schneller gefunden als member, wo erst ueber die klasse die zugriffs - adresse berechnet wird, hab ich gelesen. diese "referenzierung" ist aber im allgemeinen wenig zeitkritisch im bezug auf das gesamte Prog. , vielmehr sind optimierungen fuer rechenintensive funktionen weitaus wirksamer..
*/
Andi |
|
Nach oben |
|
|
AFE-GmdG JLI MVP
Alter: 45 Anmeldedatum: 19.07.2002 Beiträge: 1374 Wohnort: Irgendwo im Universum... Medaillen: Keine
|
Verfasst am: 17.03.2004, 10:59 Titel: |
|
|
andijota hat Folgendes geschrieben: | Aufteilen in MODULE | Am Wochenende habe ich genug Zeit, um mich mal mit diesem Thema genauer auseinanderzusetzen. Ein Projekt in mehrere Module aufzuteilen ist Prinzipiell gar nicht so schwer, es erfordert allenfalls ein wenig Denkarbeit vor dem Programmieren.
Am Besten ist es, wenn man in den Hauptprogrammquellcode nur die (Win)Main-Methode und ein oder zwei Hilfsfunktionen hineintut, die Direkt was mit der (Win)Main-Methode zu tun haben.
Alles andere sollte in extra Quellcodedateien gepackt werden, immer schön in Klassen gekapselt. (Im Prinzip für jede Klasse eine Quellcodedatei sowie ein Klassenheader)
Headerdateien müssen immer mit einer Sicherheit versehen werden, damit sie nicht doppelt includiert werden. (entweder #pragma once oder #ifndef...) Dateien, die von Headern includiert werden, sollten / *dürfen* nur andere Header sein - und zwar nur die Header, die von diesem Header benötigt werden. (benötigt im Header, nicht in der zugehörigen C++-Datei - die können dort includiert werden)
Header, die nur innerhalb einer C++-Datei benötigt werden, sollten auch nur dort includiert werden.
Das letzte Problem ist nun nur noch ein Zirkelbezug in Headern.
Wenn Klasse A Klasse B benötigt und Klasse B Klasse A, dann includiert man im Header von Klasse A nicht den Header von Klasse B sondern schreibt im Header nur eine Vorwärtsdeklaration von Klasse B und umgekehrt:
ClassA.h Code: | #pragma once
class B;
class A {
private:
B m_B;
public:
A();
~A();
} | ClassB.h Code: | #pragma once
class A;
class B {
private:
A m_A;
public:
B();
~B();
} |
AFE-GmdG
PS.: Sollte das nicht reichen, werde ich mich am Samstag hinsetzen und ein "Aufteilung in Module - Tutorial" schreiben. _________________
CPP: | float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;} |
|
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 17.03.2004, 15:39 Titel: |
|
|
Ja, das wäre echt nett und würde mir bestimmt weiterhelfen. Danke schon mal im vorraus! _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
andijota Junior JLI'ler
Anmeldedatum: 07.11.2002 Beiträge: 66 Wohnort: Berlin Medaillen: Keine
|
Verfasst am: 17.03.2004, 18:17 Titel: |
|
|
*freu*
noch was koennte zu dem thema module passen,
- wo sollte man objekte der klasse instanzieren ? und warum !
/* Objekt anlegen, aber wo ist es am besten ? : */
MyClassAny MyClassAny ;
? hat das nachteile , wenn das Objekt den KlassenNamen traegt ? funktioniert bei mir jedenfalls
andi |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|