Archive for August, 2009

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.

Umzug auf einen neuen Server

Weil ich gestern im Forum meines Hosters erfahren hab, dass dieser einen älteren Datenbankserver bald abschalten wird, habe ich gestern Abend bzw. Nacht noch schnell eine Übertragung der Blog-Datenbank durchgeführt. Allerdings hab ich jetzt ein Zeichensatzproblem: Alle deutschen Sonderzeichen wie ä, ö, ü oder ß werden auf der Seite nun so dargestellt � . Darum nicht wundern, wenn’’s jetzt im Moment seltsam aussieht. Ich bin noch am Erarbeiten einer Lösung, die dieses Problem

Slackware auf meinem Acer TravelMate 2490

Knapp vier Tage (12.08.2009) sind es her, seit dem ich meine bisherige OpenSuSE 10.3 von der Laptop Festplatte gefegt und anschließend Slackware Linux in der Version 12.2 installiert habe.

Bevor ich mich allerdings dazu entschlossen habe die Installtion durchzuführen, habe ich mich etwas in das Betriebsystem mittels einer Testinstalltion eingearbeitet. Als Linuxerin mit Erfahrung hatte ich mit dem textkonsolenbasierten Installieren und Einrichten des Systems nicht allzu viele Probleme. Man muss zunächst Patritionen für Linux auf seiner Festplatte anlegen, die bei mir schon bestanden. Allerdings habe ich Veränderungen in der Größe meiner drei Linux-Patritionen (/,/home und der Swap-Patrition) vorgenommen. Slackware bietet hier einem z.B. das Konsolenprogramm fdisk. Die angenehmere Variante zu diesem Programm stellt cfdisk dar, das ein an den nano-Editor erinnerndes Menu anbietet. Hat man seine Patritionen beisammen, kann man per Eingabe von setup mit der Installtion beginnen.

Hat man die nötigen Konfigurationen für setup vorgenommen, sodass man mit der eigentlichen Installation der Software anfangen kann, wählt man der Bequemlichkeit halber die Full Installtion. Slackware installiert dann alle Packete der insgesamt drei Installtions-CDs. Ich habe mich bei meiner Installtion ebenfalls dafür entschieden und als Standard-Window-Manager KDE gewählt. Ist alles installiert, geht’s an’s Booten und Starten des Systems.

Als richtiges Old School Linux startet diese normaler Weise im vollen Mehrbenutzerbetrieb auf der Konsole (auch Runlevel 3 genannt). Anmelden tut man sich zunächst als root, da man noch keine weiteren Benutzer erstellt hat. Nachdem Anmeldevorgang wird’s Zeit für ein bisschen grafische Oberfläche – man darf jetzt startx tippten und die Desktopumgebung wird geladen. Was mir gleich beim Blick auf den Desktop aufgefallen war, war die etwas ärmliche Auflösung von 1024 x 768. Auch wirkten die Schriften nicht ganz so klar, wie ich es vorher von SuSE gewohnt war. Das war der Auftakt zum Basteln. Bevor ich mich dem Grafiktreiber zugewenedet habe, sorgte ich erst einmal dafür, dass ich per WLAN ins Netz kann. Im Laptop ist ein Broadcom Teil verbaut. Die Eingabe von lspci nennt mir das:

root@HAL-9000:/# lspci
....
06:01.0 Ethernet controller: Broadcom Corporation BCM4401-B0 100Base-TX (rev 02)
06:02.0 Network controller: Broadcom Corporation BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (rev 02)
...

Slackware erkennt zwar das Gerät und ordnet ihm auch einen Treiber zu, allerdings funktioniert dieser bei mir WLAN-technisch gesehen nicht. Ich kann zwar per

iwconfig wlan0 essid DEIN_NETZ

den Namen des Netzwerkes setzen, nur kann man dann nicht den passenden Accesspoint (Router) setzen, was bekanntlich über

iwconfig wlan0 ap IP_DES_ACCESSPOINTS

funktioniert.
Daher greife ich zum Ndiswrapper und verwende folgende namentlich genannte Windows-Treiberdatei: bcmwl5a.inf. Mit dieser habe ich auch schon unter SuSE gute Erfahrungen gemacht.

Als das WLAN lief, wollte ich mich gleich an das Problem der mauen Auflösung machen. Mir fielen da auch gleich zwei Anlaufstellen ein, die ich gleich bearbeiten konnte:

  1. Die Konfiguration des XServers (xorg.conf)
  2. Wahl eines anderen Treibers

Ok, den Installationsprozess des Treibers wollte ich mir zunächst nicht antun, daher unternahm ich ein paar Experimente mit der xorg.conf. Und an dieser Stelle geb ich es auch gerne zu: das war die erste Begegnung mit dieser Datei mit mir. In dieser Datei gibt es mehrere Bereiche z.B. für das Gerät (Device) oder den Bildschirm (Screen).

# **********************************************************************
# Screen sections
# **********************************************************************</code>
 
# Any number of screen sections may be present.  Each describes
# the configuration of a single screen.  A single specific screen section
# may be specified from the X server command line with the "-screen"
# option.
Section "Screen"
Identifier  "Screen 1"
Device      "VESA Framebuffer"
Monitor     "My Monitor"
 
# If your card can handle it, a higher default color depth (like 24 or 32)
# is highly recommended.
 
#   DefaultDepth 8
#   DefaultDepth 16
DefaultDepth 24
#   DefaultDepth 32
 
# "1024x768" is also a conservative usable default resolution.  If you
# have a better monitor, feel free to try resolutions such as
# "1152x864", "1280x1024", "1600x1200", and "1800x1400" (or whatever your
# card/monitor can produce)
 
Subsection "Display"
Depth       8
Modes "1024x768" "800x600" "640x480"
EndSubsection
Subsection "Display"
Depth       16
Modes "1024x768" "800x600" "640x480"
EndSubsection
Subsection "Display"
Depth       24
Modes "1024x768" "800x600" "640x480"
EndSubsection
Subsection "Display"
Depth       32
Modes "1024x768" "800x600" "640x480"
EndSubsection
 
EndSection

Ok, so dachte ich mir, änderst du mal was unter dem Modus-Feld. Nachdem ich die Änderungen in die Datei eingetragen hatte, musste ich mich zunächst wieder in den Runlevel 3 begeben, um im Textkonsolen den XServer mittels startx erneut zu starten. Angezeigt wurde mir allerdings immer noch eine Auflösung in 1024 x 768. Diese ließ sich auch nicht im entsprechenden KDE Modul ändern.
Da ich mit dem XServer nicht weiter kam, musste ich mir wohl oder übel einen neuen Treiber suchen für meinen Intel Grafikchip: Intel Corporation Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (rev 03). Fündig bin ich dann auf der Seite von Intel geworden. Compilieren des Treibers war auch so eine nette Angelegenheit: das Teil wollte unbedingt das, dass sich im Verzeichnis des XServers die Header zur Mesa 3D Bibliothek befinden. Da ich mir nicht den XServer zerschießen wollte, habe ich dann den Treiber ohne die Mesa-Anbindung compiliert und installiert. Anschließend per XOrg -configure mir eine neue Konfigurationsdatei anlegen lassen und es funzte. Jetzt benutze ich eine wesentlich angenehmere Auflösung von 1280 x 800 mit klarem Bild auf dem Bildschirm. Eine Wohltat für die Augen!

Zum Abschluss meiner Installation habe ich noch benötigte Software wie OpenOffice und Netbeans draufgeschmissen. Bisher bin ich mit meinem System soweit zufrieden. An anderen Stellen muss ich dann wohl noch basteln z.B. beim automatischen Mounten von USB Sticks mit normalen Userrechten. Das muss ich bisher noch auf der Konsole als root erledigen.

Arrgh! Diese Anleitung ist für die Tonne

…oder wie ich versuchte einen Mac in eine Windows Domäne mit Active Directory zu integrieren. Da ich von Macs herzlich wenig Ahnung habe, brauchte ich erst einmal eine Anleitung, wie ich eben den Rechner in eine Windows Domäne bringe.

Vor allem konnte ich mit dem Punkt “Active Directory-Gesamtstruktur” nichts anfangen. Ich saß da und zerbrach mir den Kopf darüber, was ich da reinschreiben sollte in dieses Feld.

Dann stieß ich auf eine Anleitung, von der ich mir erhoffte, dass sie mir weiter hilft. Doch als ich anfing folgenden Abschnitt (rot markiert) durchzulesen, verstand ich so gut wie gar nichts mehr.

macanleitung

Ich saß da und sagte: “Toll, wie schön das ich nichts davon verstanden habe!”

Auf solche Anleitungen kann man getrost verzichten, da man damit nicht wirklich weiter kommt.

USB Stick mount-Probleme 2

Ich hatte einmal in einem vorangegangenen Artikel “USB Stick mount-Probleme” das Problem mit einem nicht einhängbaren (sofern man nicht als root agiert) USB Stick geschildert.

Jetzt bin ich auf die Ursache des Problems gestoßen: ich habe irgendwann im Laufe des Tages den Stick an einem Mac-Rechner stecken gehabt und Dateien darauf abgelegt. Da ich heute zum dritten Male an einem solchen Apfel-Computer (in einem Tweet hab ich die Kisten mal als unixähnliches Nicht-Linux bezeichnet) sitzen durfte, ist mir das dann direkt aufgefallen. Wahrscheinlich setzt der Mac andere Berechtigungen für den USB Stick, so dass ihn nur der root einbinden kann.

Ich habe dazu zunächst vom Mac angelegte Dateien (.Trash/ und eine Datei mit dem Namen .DS_Storage) gelöscht, Stick rausgezogen und erneut angesteckt. Kam jedoch wieder diese Fehlermeldung. Erst ein Neustart mit eingestecktem Stick brachte da Abhilfe.

Da hätte ich auch gern mal mitgemacht

Manchmal ergibt sich ein bisschen Zeit zum Lesen. Ich klicke mich munter druch die Artikel des Linux Magazin in der Server Kategorie. Lese da auch diesen Artikel, wo es um das neue Cray XT5 Cluster des ETH Zürich geht. Schade, das der im letzten Absatz erwähnte Einführungskurs schon längst vorrüber ist. :cry:

Die Vorraussetzungen (ein Laptop mit SSH) hätte ich erfüllen können. Das wäre mal ein Erlebnis der besonderen Art gewesen. Schade, Schade, Schade… :cry: