Search code examples
c++visual-studiolinker-errorscocos2d-xlnk2019

LNK2019 unresolved external symbol reference in function


Getting linker error in a basic cocos2dx app running in visual studio. Occurs when AppDelegate's "applicationDidFinishLaunching" method calls "MyGameScene"'s "singleton" method. I have already checked that the methods defined in MyGameScene.h are implemented in MyGameScene.cpp class

Error msg

Error   1   error LNK2019: unresolved external symbol "public: static class
MyGame * __cdecl MyGame::singleton(void)" (?singleton@MyGame@@SAPAV1@XZ) 
referenced in function "public: virtual bool __thiscall 
AppDelegate::applicationDidFinishLaunching(void)" 
(?applicationDidFinishLaunching@AppDelegate@@UAE_NXZ)   D:\Dev\cocos2d-2.0-x-
2.0.4\MyGame\proj.win32\AppDelegate.obj MyGame

AppDelegate.h

#ifndef  _APP_DELEGATE_H_
#define  _APP_DELEGATE_H_

#include "CCApplication.h"

/**
@brief    The cocos2d Application.

The reason for implement as private inheritance is to hide some interface call by   CCDirector.
*/
class  AppDelegate : private cocos2d::CCApplication
{
public:
AppDelegate();
virtual ~AppDelegate();

/**
@brief    Implement CCDirector and CCScene init code here.
@return true    Initialize success, app continue.
@return false   Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();

/**
@brief  The function be called when the application enter background
@param  the pointer of the application
*/
virtual void applicationDidEnterBackground();

/**
@brief  The function be called when the application enter foreground
@param  the pointer of the application
*/
virtual void applicationWillEnterForeground();
};

#endif // _APP_DELEGATE_H_

AppDelegate.cpp

#include "AppDelegate.h"
#include "cocos2d.h"
#include "MyGameScene.h"

USING_NS_CC;

AppDelegate::AppDelegate()
{

}

AppDelegate::~AppDelegate()
{
}

bool AppDelegate::applicationDidFinishLaunching()
{
// initialize director
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

// turn on display FPS
pDirector->setDisplayStats(true);

// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60);

// create a scene. it's an autorelease object
MyGame *MyGame = MyGame::singleton();
CCScene *pScene = MyGame->scene();

// run
pDirector->runWithScene(pScene);

return true;
}

// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground()
{

CCDirector::sharedDirector()->pause();

// if you use SimpleAudioEngine, it must be pause
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground()
{

CCDirector::sharedDirector()->resume();

// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

MyGameScene.h

#ifndef __MYGAME_SCENE_H__
#define __MYGAME_SCENE_H__

#include "cocos2d.h"
#include "Box2D/Box2d.h"

#define PTM_RATIO 32

USING_NS_CC;
class MyGame: public cocos2d::CCLayer {
public:

    cocos2d::CCSprite *_ball;

    // implement the "static node()" method manually
    CREATE_FUNC(MyGame)
    ;

    static MyGame *singleton();

    MyGame();
    ~MyGame();

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();

    // there's no 'id' in cpp, so we recommand to return the exactly class pointer
    cocos2d::CCScene* scene();

    // a selector callback
    void menuCloseCallback(CCObject* pSender);

    void Tick(float dt);

private:
    CCScene *_scene;

    int mWidth;
    int mHeight;

};

#endif // __MYGAME_SCENE_H__

MyGameScene.cpp

    #include "MyGameScene.h"
//#include "SimpleAudioEngine.h"
#include "Shaders.h"

using namespace cocos2d;
//using namespace CocosDenshion;

#define COCOS2D_DEBUG 1

extern "C" {
#include <pthread.h>
#include <unistd.h>
}

static MyGame *_MyGameSingleton = NULL;
static bool mIsNewFrameReceived;

MyGame* MyGame::singleton() {
    // 'layer' is an autorelease object
    if (_MyGameSingleton == NULL) {
        _MyGameSingleton = MyGame::create();

    }
    return _MyGameSingleton;
}

CCScene* MyGame::scene() {
    if (!_scene) {
        // 'scene' is an autorelease object
        _scene = CCScene::create();

        // add layer as a child to scene
        _scene->addChild(this);
    }

    // return the scene
    return _scene;
}

// on "init" you need to initialize your instance
bool MyGame::init() {
    _scene = NULL;

    if (!CCLayer::init()) {
        return false;
    }
//  CCLOG("init");
//  CCSize winSize = CCDirector::sharedDirector()->getWinSize();
//  mWidth = winSize.width;
//  mHeight = winSize.height;
    this->schedule(schedule_selector(MyGame::Tick));

    return true;
}

void MyGame::menuCloseCallback(CCObject* pSender) {
    CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

MyGame::~MyGame() {

}


MyGame::MyGame() {

}

void MyGame::Tick(float dt) {
    CCDirector *director = CCDirector::sharedDirector();
    CCSize windowSize = director->getVisibleSize();
    mWidth = windowSize.width;
    mHeight = windowSize.height;
}

UPDATE I created a new class in the project in Visual Studio itself and copied all the variables and member functions of MyGame class to it. Then, I was able to reference to the new class and compile properly.

[Copying my comment here FYI] I am able to compile the existing cocos2dx game on windows using cygwin and my colleague is able to compile the same thing on Mac using XCode. The problem is only while compiling with Visual Studio

I think Visual Studio is not compiling the MyGame file. How can I make sure that the class will be compiled?


Solution

  • I found out that I was not linking the cocos2dx libraries properly after creating the project from the template. And that was the reason for the linker error [Although the error pointed me in a different direction].
    Thanks everyone for the help!
    I am planning to list the correct steps, I used later, to create the a win32 project in Visual Studio 2012 in an existing cocos2dx project, for anyone who visits this question with a similar problem.