[Solved] I keep getting LNK2001 when trying to use global variable

Hi everyone, I have been spending hours trying to fix error LNK2001:unresolved external symbol and I can’t figure it out.

I am trying to use global variable for a character, when keyboard button is pressed, global var set to true. Character { update(){if var is true, move up} } . That is the goal, but VS keeps giving me a linking error. I extracted the code to it’s simplest form and used cocos2dx HelloWorld for testing, and problem is still there. Can someone please tell me what I am doing wrong?

global.h

#ifndef glob
#define glob
namespace global{
extern int a;
extern int b;
}
#endif

helloworld.cpp (ONLY 3 CHANGES)

#include "HelloWorldScene.h"
#include "global.h"                **(1. ADDED HEADER FILE)**       

USING_NS_CC;

Scene* HelloWorld::createScene()
{    
    int a = 0;                           **(2. INITIALIZING)**

    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

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

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    if (global::a == 0){           **(3. ADDED THIS BLOCK)**
        CCLOG("reached");
    }

**NO CHANGE BELOW THIS LINE**
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    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));

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label
    
    auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
    
    // position the label on the center of the screen
    label->setPosition(Vec2(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - label->getContentSize().height));

    // add the label as a child to this layer
    this->addChild(label, 1);

    // add "HelloWorld" splash screen"
    auto sprite = Sprite::create("HelloWorld.png");

    // position the sprite on the center of the screen
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

    // add the sprite as a child to this layer
    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
}

There is no other changes to any other files and there is no global.cpp

You had declared 2 variables called a & b but you have never defined them.

You are not defining the variables anywhere. The header declares them as extern, so the code compiles, but the linker can’t find them because you haven’t defined them anywhere. Add a .cpp file with the variables in the namespace, and it will link.

Justin

Thank you for your reply. You mentioned that I should add a .cpp file with the variables in the namespace, didn’t I do that in helloworld.cpp? (#2)? I’m coming from Java, so this is a little new to me.

In helloworld.cpp you include global.h which declares two variables as ints. Those extern int lines are telling the compiler that there are 2 ints somewhere that are global, and that they are in a namespace global, and are called a and b.

You also have to define these variables somewhere, so you should add a global.cpp file and inside the same namespace, define a and b as ints.

My Java is not great, but I think in Java, declaring and defining are the same, i.e. you have one file not two.

You could just define them at the top of helloworld.cpp

namespace global
{
    int a;
    int b;
}

Usually you pair .h and .c or .cpp together, but doing it this way illustrates how it doesn’t matter where something is defined, as long as it is defined somewhere.

1 Like

Justin,

Thanks so much. It works, which means I am suppose to define the whole namespace, not just the variables in it.

1 Like

Sort of, it’s more like if you think about a name and a thing. The declaration is the name, and the definition is the thing. It must be confusing coming from other languages. The one describes the other. Headers are useful because they can contain descriptions of things without needing to know the specific details of something, so you include a header to “know” about it, and the linker links together all the parts referring the the thing they know about.

1 Like