Search code examples
c++android-ndkcocos2d-x

Why do I get undefined reference when I place constructor definition in the body but not in the header file?


I'm following the tutorial at http://discuss.cocos2d-x.org/t/cocos3-0-tutorial-game-catchme/14258/9, using exact instructions, ie no package specified to cocos console (tried with package to same effect), and using new->Other->C/C++->Class to create the header and body (instead of 2xnew->files) Keeping things simple I just get:

HelloWorldScene.h

    #ifndef __HELLOWORLD_SCENE_H__
    #define __HELLOWORLD_SCENE_H__
    #include "cocos2d.h"        
    class HelloWorld : public cocos2d::Layer
    {
    protected:
        CatchMe* Game;
    public:
        static cocos2d::Scene* createScene();
        virtual bool init();  
        void menuCloseCallback(cocos2d::Ref* pSender);
        CREATE_FUNC(HelloWorld);
    };       
    #endif // __HELLOWORLD_SCENE_H__

HelloWorld.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    auto scene = Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

    closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));

    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);
    Game = new CatchMe();    
    auto label = LabelTTF::create("Hello World", "Arial", 24);
    label->setPosition(Vec2(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - label->getContentSize().height));
    this->addChild(label, 1);
    auto sprite = Sprite::create("HelloWorld.png");
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    this->addChild(sprite, 0);    
    return true;
}


void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
    MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif

    Director::getInstance()->end();

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

CatchMe.h

#ifndef CATCHME_H_
#define CATCHME_H_

class CatchMe {
public:
    CatchMe();
    ~CatchMe();
};

#endif /* CATCHME_H_ */

CatchMe.cpp

#include "CatchMe.h"

CatchMe::CatchMe() {
}

CatchMe::~CatchMe() {
}

I get undefined reference to CatchMe::CatchMe();

But if I remove the definition of said function from the body and place it in the header:

CatchMe() {}

Everything is peachy, it would seem..

This occurs with eclipse and building from the command line.

I'm tempted to use terms like default cunstructor to clarify but it's been too long since I last coded, plus it happens with all the methods I add... Strange


Solution

  • As per my comment under the question - the solution is to add CatchMe.cpp to build order in Android.mk. This file can be found in project tree in folder called jni. All .cpp files should be added there.

    Some time ago I created a little script (mac/linux) to help with this, details can be found here : link