Archive for the 'C\C++' Category

wxWidgets für MinGW

Wie angekündigt, sorge ich nun für eine Anleitung, wie man wxWidgets kompiliert und in einem einfachen Programm verwendet.

Vorbereitung:

wxWidgets Version: 2.18.12
MinGW Version: 3.4.5
MSYS Version: 1.0.11
Netbeans Version: 6.8 mit Plugin für C/C++

wxWidgets 2.18.12 bzw. aktuelles Stable Release als tar.gz herunterladen und in einen beliebigen Ordner mit Schreibrechten für den aktuellen User entpacken.

wxWidgets Bibliotheken kompilieren

Der Einfachheit halber sollte man MinGW im Ganzen – vor allem mit gcc und g++ – installiert haben. Daneben benötigt man die MSYS Umgebung. Beides installiert man, um Fehler zu vermeiden unter C: bzw dem aktuellen Laufwerk mit Windows. Es empfielt sich danach die bin-Verzeichnisse von msys und MinGW in die PATH Umgebungsvariable aufzunehmen.

Configure und make:

Man sollte nun nachdem wxWidgets entpackt ist die MSYS eigene Shell msys.bat (welche man im Installationsordner von msys findet) starten. Dort wechselt man nun in das wxWidgets-Verzeichnis.

cd /C/Users/AUser/wxWidgets-2812

In dem jeweiligen Ordner sollte sich eine Datei mit dem Namen configure befinden. Auf der msys-Shell gibt man zum Vorbereiten der Quellen folgendes ein:

./configure --enable-optimise --enable-static --disable-shared --enable-monolithic

Dann erhält man eine im Code optimierte, statische Bibliothek. Wer anderes konfigurieren möchte erhält mittels ./configure --help Infos zu weiteren Optionen. Ist alles ohne Abbrüche über die Bühne gegangen, so beginnt man die Buildvorgang mit einem einfachen make auf der msys-Shell.

Die Bibliotheken:

Die Bibliotheken liegen innerhalb des lib-Ordners des wxWidgets-Verzeichnis und haben hier die Endung auf .a .

Weiter gehts auf der nächsten Seite:
Continue reading ‘wxWidgets für MinGW’

Frisch kompiliert: wxWidgets

Das vergangene Wochenende habe ich genutzt um den Einstieg in wxWidgets wagen. Dazu war es erst einmal nötig aus den Quellen die Bibliotheken von wxWidgets zu erstellen. Ich persönlich habe dafür den MinGW in Kombination mit MSYS benutzt. Mit Cygwin sollte es aber auch möglich sein. Das Erstellen war an sich kein Problem, allerdings ein einfacheres wxWidgets-Programm kompilieren brachte einige Schwierigkeiten mit sich. Oft konnte der eingebundene Header trotz gegebener Includeverzeichnisse nicht gefunden werden. War dieses Problem gelöst, tauchten plötzlich Probleme beim Kompilieren des Programms – z.B. dass die Definition von strdup nicht auffindbar sei, um einen Ausschnitt aus den über 100 Fehlern zu geben – auf.

Dass ich da noch alle Haare auf dem Kopf und nicht vor Zorn ausgerissen habe, ist ein Wunder. Schließlich habe ich dann einen aller letzten Versuch gestartet, der unter der Bedingung lief, wenn’s jetzt immer noch nicht nach all den Versuchen funktioniert, dann lasse ich es. Das regt mich zwar auch übel auf, weil ich dann gescheitert bin, aber ich kann mir nicht vorwerfen lassen, dass ich es nicht versucht hätte.

Zum Glück ließ sich mit dem letzten Versuch das Programm erstellen. Damit ich mich bei späteren Ansätzen nicht erneut ärgere, habe ich mir vorsorglich eine Anleitung geschrieben, die ich dann noch hier rauf stellen werde.

C++ und grafische Oberflächen

Wenn ich in C bzw. C++ unterwegs bin, dann meist im Bereich von Konsolenanwendungen – also Programme, die in einem kleinen, schwarzen Fenster mit weiser Schrift ausgeführt werden. Programme mit bunten Buttons und sonstigen grafischen Komponenten sind bei mir bisher Mangelware.
Mir fehlt in dieser Hinsicht ein Einstiegspunkt, vor allem weil es neben den durch (kommerzielle) IDE’s bereitgestellte GUI Toolkits auch viele eigenständige Pakete. Was Windows angeht, bin ich mir unsicher zwischen MFC [1] und WinForms [2]. Schließlich gibt es noch eine freie, für verschiedene Plattformen verfügbare Alternative namens wxWidgets [3].
In Java hatte sich diese Frage mir nie gestellt, da es schließlich entsprechende Bibliotheken in der Standardbibliothek von Java bereits gibt und man daher nicht nach externen Paketen suchen muss. Drei Wahlmöglichkeiten und ich stehe mittendrin. Ich weiß auch nicht, woran ich eine Entscheidung fest machen soll. Es sollte für den Einstieg nicht zu kompliziert sein.

[1] Wikipedia: Microsoft Foundation Classes
[2] Wikipedia: Windows Forms
[3] wxWidgets Projektseite

Irrlicht Engine

Das vergagangene Wochenende habe ich genutzt, um etwas mit der Irrlicht Engine herumzuspielen. Die Irrlicht Engine ist eine Plattform, um 3D als auch 2D Spiele in C++ zu schreiben. Allerdings bin ich auch nicht weiter als zum “Hallo Welt” – Programm gekommen. Für ein Spiel fehlt mir momentan eine Idee und die Zeit. Ab und zu lese ich hier und da etwas in der Dokumentation sowie in den beiliegenden Tutorials

Eine nervös zuckende Elfengestalt umfasst dieses erste Programm.
Mal schauen, was sich noch daraus ergibt.

Warum sich meine Qt-Klassen nicht compilieren ließen

Ich staunte nicht schlecht darüber, als ich teils von Hand, teils vom QtCreator erzeugte GUI-Klassen nicht in Netbeans compilieren ließen.
Im Grunde bin ich mal wieder dabei ein sinnvolles und nutzbares Programm für den Hausgebrauch zu schreiben. Und das sollte nach Möglichkeit auch eine GUI haben. Obendrein war die Arbeit mit Qt auch mal angedacht gewesen.

Nun aber zu meinem eigentlichen Problem. Wenn ich zum Beispiel folgende Quelltexte versuchte zu compilieren, bekam ich stets diesen Fehler in Netbeans:

In function `TonerMainWindow':
/home/compiler/Netbeans-workspace/TonerV/TonerMainWindow.cpp:28: undefined reference to `vtable for TonerMainWindow'

Da wollte er weder den Konstruktor noch den Destruktor annehmen.

Der Code dazu:
tonermainwindow.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#ifndef _TONERMAINWINDOW_H
#define	_TONERMAINWINDOW_H
 
#include // ein Haufen Qt-Includes
 
class TonerMainWindow : public QMainWindow {
   Q_OBJECT 
public:
    QAction *actionBestand_anzeigen;
    QAction *actionToner_aus_geben;
    QAction *action_Beenden;
    QAction *action_ber_das_Programm;
    QWidget *centralwidget;
    QTableWidget *tableWidget;
    QPushButton *neuerTonerBtn;
    QPushButton *mengeAddBtn;
    QMenuBar *menubar;
    QMenu *menuAktionen;
    QMenu *menuInfo;
    QStatusBar *statusbar;
 
    TonerMainWindow();
    virtual ~TonerMainWindow(){ };
    void setupGUI(QMainWindow *TVMainWindow);
    void retranslateGUI(QMainWindow *TVMainWindow);
 
protected:
    //void changeEvent(QEvent *e);
 
private:
 
private slots:
 
};
 
#endif	/* _TONERMAINWINDOW_H */

tonermainwindow.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "TonerMainWindow.h"
 
TonerMainWindow::TonerMainWindow()
{
    setupGUI(this);
}
 
void TonerMainWindow::setupGUI(QMainWindow *TVMainWindow)
    {
        ... ganz viel Code ...
    } 
 
    void TonerMainWindow::retranslateGUI(QMainWindow *TVMainWindow)
    {
        ... ganz viel Code ...
    }

Ich habe anschließend gegoogelt, weil ich mit vtable so gar nichts anfangen konnte. Irgendwo habe ich dann auch gelesen, dass der vtable-Fehler eigentlich immer dann auftritt, wenn eine mit dem Schlüsselwort virtual markierte Funktion nicht definiert ist. Die einzige virtuelle Funktion wäre hier der Destruktor, der aber aus Gründen der Mehrfachvererbung in C++ immer als virtuelle Funktion definiert werden sollte.
Ahnungslos, was da eigentlich der Grund für diesen Fehler sein könnte, habe ich dann eine private Try-and-Error-Session eingelegt. Ich habe es mit Weglassen und später auch mit dem Makefile probiert. (Die Makefile-Episode lässt sich übrigens gleich hier nachlesen.)
Eine Googlesuche gab auch nicht viel her. Irgendwann hatte ich dann mal den Code so verändert, dass TonerMainWindow keine abgeleitete Klasse von QMainWindow ist, sondern eine Membervariable vom Typ QMainWindow besaß. Anschließend habe ich den Aufruf von setupGUI im Konstruktor so verändert, das da nicht mehr this sondern der Name der Membervariable da stand. Nach erfolgreichem Übersetzungsvorgang und Start des Programms, bekam ich endlich ein Fenster zu sehen.

Aber das war nicht die endgültige Lösung. Irgendwie konnte ich mich nicht ganz mit dem Gedanken abfinden, keine abgeleiteten Klassen zu verwenden. In Java mache ich das schließlich bei Swing-GUIs genauso. Aus Neugier habe ich dann Q_Object auskommentiert und es lief!
Q_Object ist ein Makro, aber was das treibt und für was das eigentlich gut sein soll, weiß ich nicht. Aber Hauptsache, es läuft. ;-)

Netbeans in der Endlosschleife

Bevor ich anfange mich über dieses merkwürdige Verhalten von Netbeans 6.7.1 für C/C++ auszulassen, kurz eine Einleitung.

Momentan experimentiere ich mit Qt in der aktuellen Fassung 4.5. Damit ich das GUI-Framework mal richtig kennen lerne, programmiere ich mir die GUI von Hand zusammen, anstatt sie mir von QtCreator erstellen zu lassen. Ich hatte auch einen Quelltext auf das Nötigste reduziert, nur bekam ich beim Compilieren und anschließenden Linken immer den Fehler “undefined reference to vtable BLABLA“. Entweder wollte er da den Constructor oder den Destructor nicht annehmen. Irgendwann bin ich auf die Idee gekommen, dass es am Makefile liegt. Daher schnell ein neues, auf vorhandenem Code basierendes Projekt erstellt.

Ich habe Netbeans schön brav einen neuen Ordner, wo ich den C++ Quelltext hineinkopiert hatte, genannt und die automatische Konfiguration angeworfen. Netbeans fängt an zu rattern, die CPU-Auslastung geht nach oben und die Mausbewegungen werden immer träger. Irgendwie kommt mir das äußerst seltsam vor. Ich greife hilfesuchend zur Konsole, tippe ein

ps -A

, um mir die laufenden Prozesse anzuzeigen, die gerade auf meinem Rechner laufen.

Und da staunte ich nicht schlecht, als ich mehrere gmake- im Wechsel mit sh-Instanzen sah. Ein getipptes

killall gmake

konnte diesen Zirkus auch nicht so einfach beenden. Dafür waren es wohl schon zu viele gmake-Prozesse. Ergo, Zwangsneustart! Dann habe ich das ganze Spiel noch einmal von neuem probiert, nur um mal sicherzustellen, ob sich dieses Verhalten reproduzieren lässt. Und das tat es. Ich habe bei meinen Versuchen herausgefunden, dass ich beim kopieren der Quelltextdateien aus Versehen das Makefile des alten Projekts mit kopiert hatte.

Hier mal ein Screenshot, wie ein normales Projektverzeichnis unter Netbeans aussieht:

netbeansverz

Das Makefile enthält einige Standarddefinitionen und Verweise auf Makefiles, die sich im nbproject-Ordner befinden.

netbeansverz1

Der Ordner build beinhaltet die sogenannten Objektdateien (also die mit der Endung .o) und dist das compilierte Programm. In meinem Projekt-Verzeichnis fehlten die Ordner build, dist und nbproject.  Jedoch braucht das Makefile den Ordner nbproject unbedingt, wegen den Verweisen auf die weiteren Makefiles. Da dieser samt Dateien fehlte, hing Netbeans durch die ständigen sh und gmake Aufrufe in einer Endlosschleife fest.

Da hilft dann nur schnell killall gmake auf der Konsole oder – wenn es schon zu viele Prozesse sind bzw. der Rechner einfach nicht mehr reagiert – Resettaste drücken. Scheint wohl einer Art Bug zu sein.

Eine Prise Quake, etwas Allegro

Nachdem ich so eine Weile auf der ReactOS Mailing Liste mitgelesen und schnell gemerkt habe, dass ich von der Betriebsystementwicklung so gut wie keine Ahnung habe, wende ich mich doch lieber etwas “einfacheren” Themengebieten zu. Bei gewissen Begrifflichkeiten, wie sie auf der Mailingliste diskutiert werden, hört es für mich einfach auf. Hier ein Beispiel:

I notice that in Windows Vista – and also Windows XP – there seems to be an undocumented field in PEB.

Was, bitte schön, soll PEB sein? Also lassen wir das mal.

Ich wollte mich sowieso mal mit etwas Grafischen beschäftigen. Mit der Bibliothek Allegro habe ich bisher ein wenig herumgespielt und zwischendurch auch mal OpenGL angetestet. Für den etwas vorbelasteten Leser in diesem Bereich, sei gesagt:

Nein, es wird nicht der nächste mega Spieletitel mit der bestechenden High-End Grafik.

(Bitte nicht in Tränen ausbrechen ;-) ) Erst einmal klein anfangen. Im Grunde habe ich vor, mit Blender erzeugte Quake 2 Modelle zu laden und anschließend zu rendern. Für das Darstellen des 3D Objektes, habe ich von Anfang an eine Verbindung aus Allegro und OpenGL vorgesehen. Nur in Sachen Format war ich mir vor kurzem noch nicht sicher. Das Format sollte aber auf alle Fälle nicht allzu kompliziert sein. Daher habe ich zunächst einiges an Exportformaten von Blender angeschaut. Von den rohen Koordinaten der einzelnen Punkte (Vertices) bishin zu XML-artigen Modelbeschreibungen war alles vertreten. Einen langsamen und fehlerträchtigen XML-Parser wollte ich mir (und dem Programm) dann doch nicht zumuten.

Die Quake-Dateiformate waren mir als sehr populär in bekannt, da einige freie Spieleengines sowie freie Spiele wie z.B. Sauerbraten davon Gebrauch machen. Vorallem lässt sich das Format auch gut in C handhaben, da sich am Anfang der Datei ein Abschnitt befindet, der zum Beispiel Informationen beinhaltet, aus wievielen Dreiecken sich ein 3D Objekt zusammensetzt. So muss man nicht ständig neuen Speicher anfordern, sondern kann die nötige Menge vorab anfragen. Um das Dateiformat zu verstehen, benutze ich die bekannte Spezifikation von Daniel E. Schoenblum.

Jetzt muss ich mir nur noch einen Weg erarbeiten, wie ich die Daten aus der Datei sinnvoll mit Allegro verwenden kann.

Wenn malloc sich mal mehr nimmt – Teil 2

Noch immer bin ich auf der Suche nach einer Erklärung für malloc’s Verhalten Um zu schauen, was malloc so unter Windows treibt, habe ich das Programm unverändert mit Hilfe von NetBeans und Cygwin für Windows XP übersetzt, sowie anschließend mit dem Debugger laufen lassen.

Beim Blick ins Debuggerfenster dachte ich, dass ich nicht richtig sehe.

Debuggerlauf unter Windows

Debuggerlauf unter Windows

NetBeans zeigt mir insgesamt 20(!) C-Strings in buf an.Dabei hatte ich aber nur drei bestellt. Irgendwie ist mir das nicht geheuer bei dieser Konstellation.

Update:

Mittlerweile habe ich die Fragestellung ins Forum verlegt und auch eine Antwort erhalten. Schuld daran ist das sogenannte Alignment, sprich die einzelnen Bytes werden (unter einem 32 Bit System) in, für den Prozessor, handliche vierer Packs unterteilt.

Wenn malloc sich mal mehr nimmt

Über dieses eigenartige Verhalten von malloc, bzw. in meinem Fall calloc, staune ich im Moment, da ich bisher keine mir einleuchtende Erklärung gefunden habe. Kurze Erklärung, wovon ich eigentlich rede: calloc und malloc sind zwei Funktionen, die man in der Programmiersprache C für das dynamische Anfordern von Speicher zur Laufzeit verwendet.

Dynamische Speicherverwaltung ist an sich ganz praktisch, wenn man zum Beispiel aus einer Datei mehrere Zeilen mit Koordinaten (x,y,z in einer Zeile) lesen will und man die genaue Anzahl der Zeilen nicht kennt. Um dieses Problem angehen zu können, habe ich mich für die Verwendung des berühmt berüchtigten Doppelpointerschar **buf - entschlossen. (Der Doppelpointer entspricht etwa einem zweidimensionalen Array: z.B. char buf[3][10])

Etwas Beispielcode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio .h>
#include <stdlib .h>
#include <string .h>
#define SIZE 3
 
int main(int argc, char** argv) {
 
    char **buf;
    int i;
    char* ch = "foo";
 
    //In buf soll spaeter der Inhalt von SIZE C-Strings Platz finden
    buf = (char**) calloc(SIZE, sizeof (char*));
 
    for(i=0; i < SIZE; i++){
        // Jeder einzelne C-String soll eine Zeichenlaenge von 128 inklusive dem Null-Byte haben
        buf[i] = (char*) calloc(128,sizeof(char));
        // Kopiere den Text von ch an die i-te Speicherstelle von buf
        strcpy(buf[i],ch);
    }
 
    for(i = 0; i < SIZE; i++) {
        printf("%s -- ", buf[i]);
        printf("%i\n", i);
    }
 
    for(i = 0; i < SIZE; i++)
        free(buf[i]);
 
    free(buf);
 
    return (EXIT_SUCCESS);
}

Continue reading ‘Wenn malloc sich mal mehr nimmt’

Innere Klassen / Structs in C++

Heute hab ich was Neues gelernt, was C++ betrifft.
Ehrlich gesagt, wenn man mich gefragt hätte, ob folgender Code

class MyOuterClass {
    private:
 
        struct Data {
            private:
                int an_integer;
            public:
		Data();
		~Data();
		int get_an_integer();
		void set_an_integer(int value);
	 } Data;
 
    public:
        MyOuterClass();
	~MyOuterClass();
};

in C++ verfassbar wäre, hätte ich mit “Nein” geantwortet. Solch einen Quelltext hatte ich vorher noch nie in einem meiner E-Books zur C++ Programmierung gesehen. :-o
Hätte es nicht einen neuen Eintrag im C++ Unterforum von programmiersprachen.de gegeben, so hätte ich womöglich nicht von diesem Feature erfahren.
Übrigens kann man anstatt einer struct auch eine Klasse deklarieren – gäb’s da nicht ein paar kleinere syntaktische Besonderheiten, könnte man das glatt als einen Java-Quelltext ansehen.

C++ überrascht mich immer wieder. Auch die structs können etwas mehr als in C. Die Unterteilung in Sichtbarkeitsbereiche mittels private bzw. public kennt C zwar nicht, aber man kann mit Funktionspointern in der struct, die Verwendung von struct-eigenen Methoden nachbauen.