CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Oct 2005
    Posts
    19

    Question [Linker error] undefined reference to `GetStockObject@4'

    Hello. I'm currently building an application to solve a sort of game called Sudoku. I use Dev-C++. When I try to compile/link my program I get the following:

    C:\C++\Sudoku\Sudoku.o(.text+0xe5) In function `ZSt13__cmath_powerIdET_S0_j':
    [Linker error] undefined reference to `GetStockObject@4'
    C:\C++\Sudoku\Sudoku.o(.text+0x4a1) In function `ZN6SudokuC1EP11HINSTANCE(int **)':
    [Linker error] undefined reference to `GetStockObject@4'
    [Linker error] undefined reference to `WinMain@16' C:\C++\Sudoku\Sudoku.o(.text+0x4a1) ld returned 1 exit status
    C:\C++\Sudoku\Makefile.win [Build Error] [Sudoku.exe] Error 1

    I know that the WinMain@16 means that I don't have a WinMain or Main method (see code below), but that is because it will be included later. On the other hand, I have no clue why I'm getting the "undefined reference" messages. So why do I get them and what do I do about them? Thank you.

    CppMaster, may the code be with you

    Here's my code:
    Code:
    //Sudoku.h
    
    #include<windows.h>
    #include<WinX.h>
    
    class Sudoku {
        private:
            static Sudoku current;
            int values[9][9];//if 0, the value is unknown
            bool constVals[9][9];//if true, value was given by user
            explicit Sudoku(HINSTANCE, int**);
            inline bool available(int, int, int);
            
            //for display purposes
            HWND mainWnd;
            HWND numFields[9][9];
            HWND solveButton;
            void process();
            
        public:
            Sudoku(){}
            Sudoku createSudoku(HINSTANCE, int**);
            void display();
            bool solve();
            void update();
            static Sudoku currentSudoku(){ return current; }
            void setValues(int**);
    };
    
    //Sudoku.cpp
    
    #include"Sudoku.h"
    #include<cctype>
    #include<cmath>
    
    Sudoku Sudoku::current;
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int strToInt(char*, int, int index);
    char* intToStr(int);
    
    Sudoku::Sudoku(HINSTANCE hInst, int** vals)
    {
        for(int x = 0; x < 9 ; x++){
            for(int y = 0; y < 9 ; y++){
                if(vals) constVals[x][y] = true;
                values[x][y] = vals[x][y];
            }
        }
        WNDCLASS wndclass;
            wndclass.style = CS_HREDRAW | CS_VREDRAW;
            wndclass.lpfnWndProc = WndProc;
            wndclass.cbClsExtra = 0;
            wndclass.cbWndExtra = 0;
            wndclass.hInstance = hInst;
            wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
            wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
            wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
            wndclass.lpszMenuName = NULL;
            wndclass.lpszClassName = "SU_15_X";
        if(!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("ERROR, could not register wndclass!"), "Sudoku", 
                       MB_ICONERROR);
        }
        int eBoxWidth = 27;
        int eBoxHeight = 27;
        int buttonWidth = 75;
        int buttonHeight = 40;
        mainWnd = CreateWindow("SU_15_X", TEXT("Sudoku"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
                               CW_USEDEFAULT, eBoxWidth*9, eBoxHeight*9 + buttonHeight, NULL,
                               NULL, hInst, NULL);
        for(int x = 0; x < 27; x++){
            for(int y = 0; y < 27; y++){
                numFields[x][y] = CreateWindow("EDIT", NULL, WS_CHILD|WS_VISIBLE,
                        x*27,y*27,eBoxWidth, eBoxHeight, mainWnd ,NULL,hInst,NULL);
                if(values[x][y] > 0)SetWindowText(numFields[x][y],TEXT(intToStr(values[x][y])));
            }
        }
        solveButton = CreateWindow("BUTTON", TEXT("Solve"), BS_DEFPUSHBUTTON|WS_CHILD|WS_VISIBLE,
                            CW_USEDEFAULT, CW_USEDEFAULT, (int)((eBoxWidth*27 - buttonWidth)/2),
                            (int)((eBoxHeight*27 - buttonHeight)/2), mainWnd, NULL, hInst, NULL);
    } 
    
    Sudoku Sudoku::createSudoku(HINSTANCE hInst, int** vals)
    {
        Sudoku s = Sudoku(hInst, vals);
        Sudoku::current = s;
        return s;
    }
    
    bool Sudoku::solve()
    {
        bool test = false;
        for(int x = 0; x < 9; x++){
            for(int y = 0, i; y < 9; y++){
                if(values[x][y] > 0)continue;
                for(i = 1; i < 10; i++){
                    if(available(i, x, y)){
                        if(!test) test = true;
                        else {
                            test = false;
                            break;
                        }
                    }
                }
                if(test) values[x][y] = i;
            }
        }
        return true;
    }
    
    bool Sudoku::available(int val, int row, int line)
    {
        if(row > 9) return false;
        if(line > 9) return false;
        for(int x = 0; x < 9; x++){
            if(values[x][line] <= 0) continue;
            if(values[x][line] == val) return false;
        }
        for(int y = 0; y < 9; y++){
            if(values[row][y] <= 0) continue;
            if(values[row][y] == val) return false;
        }
        for(int x = ((row - (row % 3)) / 3); x < 3; x++){
            for(int y = ((line - (line % 3))/3); y < 3; y++){
                if(values[x][y] <= 0) continue;
                if(values[x][y] == val) return false;
            }
        }
        return true;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static Sudoku sudoku;
        switch(message)
        {
            case WM_CREATE:
                sudoku = Sudoku::currentSudoku();
                return DefWindowProc(hWnd, message, wParam, lParam);
            case WM_COMMAND:
                sudoku.update();
                sudoku.solve();
                return 0;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    
    void Sudoku::update()
    {
        char number;
        for(int x = 0; x < 9; x++){
            for(int y = 0; y < 0; y++){
                if(GetWindowText(numFields[x][y], &number, 1))
                    values[x][y] = strToInt(&number, 1, 0);
                else values[x][y] = 0;
            }
        }       
    }
    
    inline int strToInt(char* str, int length, int index)
    {
        int ans = 0;
        for(int i = length - 1; i > index - 1; i--){
            if(!std::isdigit(str[i])) return (-1);
            ans += (((int)str[i]) - ((int)('0')))*int(pow(10,(i+1) - length));
        }
    }
    
    inline char* intToStr(int i)
    {
        char* str = new char[12];
        int temp = i;
        int length;
        for(length = 0; temp != 0; i++)
            temp = (int)(temp / 10);
        temp = i;
        int temp2 = 0;
        for(int j = length; j > 0; j--){
            temp2 = (int)(temp/std::pow(10.0, j));
            str += char(temp2 + (int)('0'));
            temp -= temp2*int(pow(10,j));
        }
        return str;
    }

  2. #2
    Join Date
    Jun 2005
    Posts
    1,255

    Re: [Linker error] undefined reference to `GetStockObject@4'

    The game of Sudoku is fascinating.

    What is the type of your project? "Win 32 Gui", "Win32 Console", or something else? I'm not sure that GetStockObject is available for a "Win32 Console" project.

  3. #3
    Join Date
    Sep 2004
    Location
    Italy
    Posts
    389

    Re: [Linker error] undefined reference to `GetStockObject@4'

    edit, nvm.

  4. #4
    Join Date
    Oct 2005
    Posts
    19

    Re: [Linker error] undefined reference to `GetStockObject@4'

    It should be a win32 gui (tho I created an empty project with Dev-Cpp if that's what you were refering to).

  5. #5
    Join Date
    Jun 2005
    Posts
    1,255

    Smile Re: [Linker error] undefined reference to `GetStockObject@4'

    I'm afraid, that the "Win 32 GUI" option is not set in your project.
    By default, when you create an empty application, it is set to "Win32 Console".
    Select in the Menu bar "Project/"Project Options", a dialog box pops up and you will see right away what is the type of your project.
    Another way is to check the presence or absence of "-mwindows" in Makefile.win on the line starting with "LIBS".
    "-mwindows" is required for Windows libraries.

  6. #6
    Join Date
    Oct 2005
    Posts
    19

    Talking Re: [Linker error] undefined reference to `GetStockObject@4'

    It works! Thanks a bunch : )

  7. #7
    Join Date
    Apr 2005
    Location
    Livonia Michigan
    Posts
    142

    Re: [Linker error] undefined reference to `GetStockObject@4'

    I might be a little naive, but I believe as long as you include the Gdi32 library you can use GetStockObject regardless of what kind of project you have.
    The Strawdog's out in the street

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: [Linker error] undefined reference to `GetStockObject@4'

    Quote Originally Posted by olivthill
    I'm afraid, that the "Win 32 GUI" option is not set in your project.
    By default, when you create an empty application, it is set to "Win32 Console".
    You can call *any* Windows API function in either console or GUI apps. In a Win32 console app, you can create message boxes, windows, menus, dialog boxes, select or save files/print/choose fonts, etc. using the common dialogs -- anything that a GUI app can do.

    If Dev-C++ doesn't link in the correct library if "Win32 Console" is selected, then that is a bug in Dev-C++.

    Regards,

    Paul McKenzie

  9. #9
    Join Date
    Apr 2005
    Location
    Livonia Michigan
    Posts
    142

    Re: [Linker error] undefined reference to `GetStockObject@4'

    well, it's not really a bug in dev, you just have to add the library yourself.

    If you want to add the library to the project you go to Project/Project Options, click the parameters tab, then add "-lGdi32" to the Linker commands.

    To add Gdi32 to everything you compile go toTools/Compiler Options, check "Add these commands to the linker command line" and add "-lGdi32" to the text box below it.
    The Strawdog's out in the street

  10. #10
    Join Date
    Aug 2002
    Posts
    78

    Re: [Linker error] undefined reference to `GetStockObject@4'

    I just had this with the latest and greatest of gcc and minwin and Eclipse (IDE) when compiling a simple win32 "Hello" program that pops up a window with a button.

    Here are the hoops I had to jump through:

    1. -mwindows is sweet, but doesn't do all the work. In fact, it doesn't do any work, as far as I can tell.

    2. I thought it odd, but I had to add Gdi32 to the linker's list of libraries under Eclipse. Note: Some web pages say you have to add libgdi32.a, but the linker chokes when you do this.

    Somewhere along the line, Gdi32 gets munged into libgdi32.a. As the linker line in the output is a g++ command line with -lGdi32, I'm guessing the g++ wrapper does this before calling the linker, said part is not shown in the output.

    3. Going back, I removed -mwindows from the compiler options, and it still built and ran after a clean, full rebuild.



    So, to sum up, I'm not sure what -mwindows was supposed to do, and to get this to work, adding Gdi32 as a library to the linker step (in the Eclipse interface) was sufficient, but adding libgdi32.a, which (I'm guessing) "Gdi32" turns into downstream, choked.

    As a side note for HMI developers for these tools, you can see how being too clever by half in an attempt to clean up the clumsiness of the low level command lines can still mess things up.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured