1

I seriously think I might have checked every mach-o link id error post on stackOverFlow and couldn't find a solution to my problem... I dont fully understand how the linker works yet so I can't always figure out how to fix these bugs when they come up...

Ive been following these YT tutorials some guy named Konrad Jablonski put up about making rpg games with C++ [using SDL2 and SDL.image framworks]... I learned a lot about rpg game logic -- it was definitely a good learning experience for someone with a firm grasp of the basics, but new to c++...

At this point in the tutorials he's seperating one class into numerous subclasses... And everything was working fine until I started breaking up the one class into numerous different .cpp and .h files... The error message says:

- Undefined symbols for architecture x86_64:

- "cSprite::draw()", referenced from:

- gMain::gameLoop() in gMain.o

*- ld: symbol(s) not found for architecture x86_64*

- clang: error: linker command failed with exit code 1 (use -v to see invocation)

The whole project was bug free up until compilation, and I don't fully understand how the compiler works so I don't know where to start when attempting to adjust it... I can put up the classes if anyone knows anything about these type of errors and wants to help -- If not I'd still appreciate anything that would lead me in the right direction as far as figuring out how the linker works... Im still new to stackoverflow so I won't be able to +1 responses until I get more active but when I get the chance I'll return the favor

-------- gMain.cpp ---------

#include <iostream>
#include "stdafx.h"
#include "gMain.h"


using namespace std;

gMain::gMain(int passed_screenWidth, int passed_screenHeight)
{
    screenWidth = passed_screenWidth;
    screenHeight = passed_screenHeight;

    // quit boolean
    quit = false;

    // create instance of cSDL class
    csdl_setup = new cSDL_Setup(&quit, screenWidth, screenHeight);

    grass = new cSprite(csdl_setup->getRenderer(), "data/images.jpeg", 0, 0, screenWidth, screenHeight);

    bruce_Lee = new cSprite(csdl_setup->getRenderer(), "/Users/jamesbryant/Desktop/gamee/gamee/lee.bmp", 300, 250, 50, 100);


}

gMain::~gMain(void)
{
}

void gMain::gameLoop(void)
{
    // game loop logic
    while (!quit && csdl_setup->getMainEvent() ->type != SDL_QUIT)
    {
        csdl_setup->begin();

        grass->draw();
        bruce_Lee->draw();


        csdl_setup->end();

    }
}

------ gMain.h ------

#ifndef __game__gMain__
#define __game__gMain__
#pragma once

//#include <iostream>
//#include <SDL2/SDL.h>
//#include <SDL2_image/SDL_image.h>
//#include <SDL2/SDL_audio.h>
#include "cSDL_Setup.h"
#include "cSprite.h"

using namespace std;

class gMain
{
public:
    gMain(int passed_screenWidth, int passed_screenHeight);
    ~gMain(void);
    void gameLoop();

private:
    int screenWidth;
    int screenHeight;

    bool quit;

    //cSprite
    class cSprite* grass;

    class cSprite* bruce_Lee;


    // cSDL_Setup class object
    class cSDL_Setup* csdl_setup;
};

#endif /* defined(__game__gMain__) */

----- cSprite.cpp -------

#include "stdafx.h"
#include "cSprite.h"
//#include "gMain.h"
//#include <SDL2/SDL_main.h>
//#include <SDL2/SDL.h>
//#include "cSDL_Setup.h"

using namespace std;

void draw(SDL_Renderer, SDL_Texture, SDL_Rect);

cSprite::cSprite(SDL_Renderer* passed_renderer, string filePath, int x, int y, int w, int h)
{
    renderer = passed_renderer;

    //... image
    image = NULL;
    image = IMG_LoadTexture(renderer,filePath.c_str());

    // image error message
    if (image == NULL)
    {
        cout<<"Couldnt load image..."<<filePath.c_str()<<endl;
    }

    //image dimensions
    rect->x = x;
    rect->y = y;
    rect->w = w;
    rect->h = h;
};

cSprite::~cSprite(void)
{
    SDL_DestroyTexture(image);
}

//get methods
//SDL_Rect* cSprite::getRect()
//{
//    return rect;
//}

//get methods
//SDL_Texture* cSprite::getImage()
//{
//    return image;
//}

void cSprite::draw()
{
    SDL_RenderCopy(renderer, image, NULL, rect);
}

------- cSprite.h --------

#ifndef __game__cSprite__
#define __game__cSprite__
#pragma once

#include <iostream>
#include <SDL2/SDL_main.h>
#include <SDL2/SDL.h>

using namespace std;


class cSprite
{
public:
    cSprite(SDL_Renderer* passed_renderer, string filePath, int x, int y, int w, int h);
    ~cSprite(void);

    void draw();

private:
    SDL_Texture* image;
    SDL_Rect* rect;

    SDL_Renderer* renderer;
};

#endif /* defined(__game__cSprite__) */

------ cSDL_Setup.cpp -------

#include "stdafx.h"
#include "cSDL_Setup.h"
//#include "gMain.h"

using namespace std;

cSDL_Setup::cSDL_Setup(bool* quit, int screenWidth, int screenHeight)
{
    // create window
    window = NULL;
    window = SDL_CreateWindow("rWDY_pWDR", 100, 100, screenWidth, screenHeight, SDL_WINDOW_RESIZABLE);

    // if window couldnt be created...
    if (window == NULL)
    {
        cout<<"Window couldnt be created..."<<endl;

        *quit = true;
        //exit(0);
    }

    //create renderer
    renderer = NULL;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    // initialize images
    mainEvent = new SDL_Event();

}

cSDL_Setup::~cSDL_Setup(void)
{
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    delete mainEvent;
}

//get methods
SDL_Renderer* cSDL_Setup::getRenderer()
{
    return renderer;
}

SDL_Event* cSDL_Setup::getMainEvent()
{
    return mainEvent;
}

void cSDL_Setup::begin()
{
    SDL_PollEvent(mainEvent);
    SDL_RenderClear(renderer);
}

void cSDL_Setup::end()
{
    SDL_RenderPresent(renderer);

}

------- cSDL_Setup.h -------

#ifndef __game__cSDL_Setup__
#define __game__cSDL_Setup__
#pragma once


//#include <iostream>
//#include "gMain.h"

using namespace std;

class cSDL_Setup
{
public:
    cSDL_Setup(bool* quit, int screenWidth, int screenHeight); // 1 parameter(s): 'quit'
    ~cSDL_Setup(void);

    // 'get' functions
    SDL_Renderer* getRenderer();
    SDL_Event* getMainEvent();

    void begin();
    void end();

private:
    SDL_Window* window;
    SDL_Renderer* renderer;
    SDL_Event* mainEvent;

};

#endif /* defined(__game__cSDL_Setup__) */

-------- stdafx.h ---------

#ifndef gamee_stdafx_h
#define gamee_stdafx_h
#pragma once

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
#include <SDL2_mixer/SDL_mixer.h>



#endif
  • Make sure the module where `cSprite::draw()` is defined is part of your target. – CouchDeveloper Oct 18 '13 at 08:03
  • ... and how would I go about doing that @CouchDeveloper... Build Phases ? – TWiSTED_CRYSTALS Oct 18 '13 at 11:22
  • 1
    Using the "Compiled Sources" section in the "Build Phases" pane is one option. The other is to select the file, then open the "Utility Window" (the area on the right), locate the "Target Membership" section, and set the checkmark beneath the targets where you want to add this file. – CouchDeveloper Oct 18 '13 at 11:26
  • all my .cpp files are properly targeted @CouchDeveloper... my header files arent targeted and when I added them to 'compiled sources' in the past nothing changed... It says a .o file is missing but isnt that an object of a .cpp file created at compilation?... the gMain.cpp file that creates the gMain.o file is already included in 'compiled sources'... – TWiSTED_CRYSTALS Oct 19 '13 at 05:30
  • Header files cannot be assigned to targets, because they won't get compiled (directly). Instead, header files are included by modules. _One_ module and all its direct and indirect headers build up a _translation unit_. This TU is the thing that will be _compiled_ by the compiler generating a corresponding .o file. The set of .o files will then be linked by the linker into a program or library or archive. Undefined symbol "cSprite::draw() referenced from: gMain::gameLoop()" means, that there is no function with that name in any of the compiled .o files - and it was called in `gMain::gameLoop`. – CouchDeveloper Oct 19 '13 at 09:02
  • I'm looking right at it though, it's def not missing... Can I send you the project ? It's only four small classes -- each with a .h file to go with it... @CouchDeveloper – TWiSTED_CRYSTALS Oct 19 '13 at 16:34
  • Ensure the member function cSprite::draw() is actually *defined*. Please *edit* your original post and show the code for this function. Show also the code where it will be called from within gMain::gameLoop. – CouchDeveloper Oct 21 '13 at 06:55
  • gonna put the code up right now... I changed some things since that day so Im getting new errors... but its still the same concept -- it wont work because that one thing is missing – TWiSTED_CRYSTALS Oct 21 '13 at 18:11
  • Now, the cSprite::draw() member function is properly implemented. There are is a bug, which doesn't explain the missing definition, though (in the destructor delete the allocated resources). Also, do not specify `void` as parameter in the destructor - and the forward declaration within the class definition seems unusual. I still suspect, that the module isn't properly linked. – CouchDeveloper Oct 21 '13 at 19:55
  • @CouchDeveloper youre right... all the errors i get come after compilation now -- idk how to deal with those – TWiSTED_CRYSTALS Oct 21 '13 at 21:57
  • I suspect the project isn't setup correctly. You may create a new one from scratch. Usually, this shouldn't be a problem. You need to create a C++ project from a project template, add the sources, link the SDL library and that's it. If you don't know how to do that, Xcode provides comprehensive documentation for each of these steps. – CouchDeveloper Oct 22 '13 at 07:15

0 Answers0