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?
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.