multiple definition beim MinGW



  • So,
    ich habe nun ein relativ simples Programm.
    Es erzeugt 2 Fenster.
    Ich hab ein HWND namens ToolDialog definiert und es in eine include gepeckt.
    Nun sollen das Hauptprogramm und ein Unterprogramm (da sind nur die Fensterprozeduren drin) darauf zugreifen. Aaber er meint ich habe ToolDialog doppelt definiert. Hier mal der Code:

    winprocedures.h

    #ifndef __WINPROCEDURES_H
    #define __WINPROCEDURES_H
    #include <windows.h>
    HWND ToolDialog;
    
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK ToolProc        (HWND, UINT, WPARAM, LPARAM);
    
    #endif
    

    main.cpp

    #include <windows.h>
    #include "winprocedures.h"
    
    char MainClassName[ ] = "WorldGenerator";
    char ToolClassName[ ] = "ToolWindow";
    
    /*  Declare Windows procedure  */
    
    /*  Make the class name into a global variable  */
    
    int WINAPI
    WinMain (HINSTANCE hThisInstance,
             HINSTANCE hPrevInstance,
             LPSTR lpszArgument,
             int nFunsterStil)
    
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Main Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = MainClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
         wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        wincl.hbrBackground = (HBRUSH) (COLOR_WINDOW);
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
        /* Register the child window */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = ToolClassName;
        wincl.lpfnWndProc = ToolProc;      /* This function is called by windows */
        wincl.cbSize = sizeof (WNDCLASSEX);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
         wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        wincl.hbrBackground = (HBRUSH) (COLOR_WINDOW);
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               MainClassName,         /* Classname */
               "World Generator v1.0",       /* Title Text */
               WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               CW_USEDEFAULT,       /* The programs width */
               CW_USEDEFAULT,       /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        ToolDialog = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               ToolClassName,         /* Classname */
               "Toolbox",       /* Title Text */
               WS_POPUPWINDOW|WS_CAPTION, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               50,       /* The programs width */
               100,       /* and height in pixels */
               hwnd,        /* The window is a child-window to Main Window */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nFunsterStil);
        ShowWindow (ToolDialog, nFunsterStil);
    
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    

    winprocedures.cpp

    #include "winprocedures.h"
    
    #include "Button/c_mybutton.h"
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK
    WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
                break;
            case WM_DESTROY:
                DestroyWindow(ToolDialog);
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
    
                break;
            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    
    LRESULT CALLBACK
    ToolProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
      static C_MyButton *Wasser, *Ebene, *Berg;
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
                break;
            case WM_DESTROY:
                break;
            default:                      /* for messages that we don't deal with */
                return FALSE;
        }
    
        return TRUE;
    }
    

    c_mybutton.h / .cpp haben nichts damit zu tun. die erstellen mir nur nen button.

    Hab ich irgendwas übersehen??

    cYA && thx
    DjR



  • Kannst du das mal so online stellen, also mit allem drum und dran (Button/c_mybutton.h ...), das man es komplett kompilieren kann? 🙂
    Dann könnten wir dir nämlich viel besser helfen.



  • mach ich,
    ürbigens: wenn ich ToolDialog in der Main definiere und als extern in winprocedure.cpp, dann klappt's. Kann mir das einer erklären??
    [url] mitglied.lycos.de/DocJunioR/TGen.zip [/url]

    Ich hoffe, ich hab nix vergessen.

    cYa
    DjR



  • du hast eine definition in einer Header Datei - das kann ja nicht gut gehen (es sei denn, du haettest du haettest nur eine UeE!

    Naja..
    Bezeichner die mit unterstrich beginnen und dann ein grossbuchstaben haben sind fuer den compiler reserviert!
    Und genauso verhaelt es sich mit Bezeichnern die __ in ihrem Namen haben!

    [ Dieser Beitrag wurde am 16.11.2002 um 13:14 Uhr von Shade Of Mine editiert. ]



  • Ich hab mir das gerade mal angeschaut und du hast sogar recht. Laut ANSI-Standard sind System-Header (die ANSI-internen Standard-Header) mit __ defined. Es ist zwar nicht verboten, dies für andere Headerdateien zu benutzen, aber nicht unbedingt Oxford Stil. Du wirst aber einsehen, dass ich nicht sämtliche von mir geschriebenen Header-Dateien umstricken möchte. Da bin ich ja ewig beschägtigt. Wie auch immer. Ich gelobe Besserung 🙂
    Ich finde es ein wenig komisch, dass sich der eigentliche Fehler in einem multiple definition niederschlägt. Naja, auch hier scheint mir nur die Möglichkeit zu bleiben, das Ganze mit einem extern zu deklarieren, oder?
    Schade eigentlich.
    Mal so ganz nebenbei, kann mir jemand sagen, wo mein 2. Fenster abgeblieben ist? es müsste ja wenigstens sichtbar sein.. 😞

    cYa
    DjR

    [ Dieser Beitrag wurde am 16.11.2002 um 14:41 Uhr von DocJunioR editiert. ]



  • Wieso erstaunt es dich, dass du eine multiple definition hast?

    Du definierst in jeder UeE ToolDialog -> und das wirft dir der linker um die ohren.

    Genau fuer sowas wurde extern erschaffen (aber ich mag sowieso keine globalen variablen)

    Deine erklaerung zu _ und __ kapiere ich nicht - es ist verboten, also machs nicht.



  • Ich würde dabei nur einen etwas anderen Effekt erwarten. Aber ich bin kein Compilerdesigner und dieser Fehler hat bestimmt seine Daseinsberechtgung.. Und sei es nur, um kleine JunioR's zu verwirren, die mal wieder viel zu wenig Schlaf bekommen haben... 😉

    In der Beschreibung zum ANSI-Standard steht ".. sollte nicht benutzt werden..", nicht "ist absolut verboten" - wie auch immer.
    Mich würde aber mal interessierenm warum mir nur ein Fenster angezeigt wird. Hast du da zufällig nen Tipp?

    http://acm.uva.es/problemset/gnudoc/cpp/Once-Only.html

    [ Dieser Beitrag wurde am 16.11.2002 um 14:51 Uhr von DocJunioR editiert. ]



  • Den Standard muss man halt lesen koennen...

    shall not heisst, soll nicht und wenn der Standard sagt, du sollst das nicht tun, dann tust du das auch nicht.

    must not ist eine zuharte formulierung, deshalb sagt man immer shall not!



  • Wie auch immer..
    Ich denke nicht, dass diese Diskussion zu etwas führt. Es ist ja eindeutig, dass Du das ein wenig enger siehst als ich. Naja, wo wären wir, wenn wir alle das Gleiche machen würden.
    Mich interessiert momentan eh mehr, warum ich nur ien Fenster zu sehen bekomme..



  • Childs von Windows werden im WM_CREATE erstellt, semantisch ist es so wie du es machst falsch (ka ob das der Grund fuer das Problem ist)

    dann waerst du auch dein globales ToolDialog los 😉



  • Daran liegt's wohl nicht.
    Ist aber imho kein WinGW-Problem.
    ich werd also einfach mal im WinAPI-Forum fragen.

    cYa
    DjR


Anmelden zum Antworten