0

I don't know how to export a static variable that is inside a template to my executable.

I'm using entityx library that has a template for components:

Entity.h :

struct BaseComponent {
public:
  typedef size_t Family;
protected:
  static Family family_counter_; //THIS!!
};

template <typename Derived>
struct Component : public BaseComponent {
 public:
  typedef ComponentHandle<Derived> Handle;
  typedef ComponentHandle<const Derived, const EntityManager> ConstHandle;

private:
  friend class EntityManager;
  /// Used internally for registration.
  static Family family();
};

Entity.cpp:

BaseComponent::Family BaseComponent::family_counter_ = 0;

Now I have my library that links to entityx and uses that: World.hpp:

#include <entityx/entityx.h>

namespace edv {
class Transform : public entityx::Component<Transform> {
public:
    Transform();
};

class World {
public:
    World();
    entityx::Entity createEntity();
private:
    entityx::EventManager m_events;
    entityx::EntityManager m_entities;
};
}

World.cpp:

#include <Endavant/game/World.h>
#include <iostream>

namespace edv {
Transform::Transform() {
}

World::World(): m_entities(m_events){
}

void World::update() {
}

entityx::Entity World::createEntity() {
    auto e = m_entities.create();
    e.assign<Transform>();
    auto c = e.component<Transform>();
    if (c.valid()) {
        std::cout<<"createEntity componenthdnlr OK!!"<<e.id()<<std::endl;
    } else {
        std::cout<<"createEntity componenthdnlr INVALID!!"<<e.id()<<std::endl;
    }
    return e;
}

}

Now I build an executable "myprogram.exe" that links to my library EDV and to entityx:

#include <Endavant/Root.h>
#include <Endavant/game/World.h>

void test() {
    auto entity = edv::Root::get().getWorld().createEntity();
    auto comp = entity.component<edv::Transform>();

    if (comp.valid()) {
        std::cout<<"test componenthndlr VALID!!"<<entity.id()<<std::endl;
    } else {
        std::cout<<"test componenthndlr INVALID!!"<<entity.id()<<std::endl;
    }
}

int main() {

    try {
        edv::Root::get().init();
        test();
        edv::Root::get().run();
    } catch (std::exception & e) {
        std::cout<<e.what()<<std::endl;
    }
    return 0;
}

When I execute "myprogram.exe" it outputs:

createEntity componenthdnlr OK!!
test componenthndlr INVALID!!

I debugged the application and it seems that there are two instances of "family_counter_" static variable one for my dll, and another for the executable "myprogram.exe".

When I compile the same in Linux, it works as expected:

createEntity componenthdnlr OK!!
test componenthndlr OK!!

So I think it should be something about Windows DLL visibility in GCC. I'm new to this Windows DLL world and I don't know exactly where and what I have to export, to make this work.

I'm using MSYS2 with GCC 5.2.0 to compile this. Thank you

FrameBuffer
  • 757
  • 1
  • 7
  • 26

1 Answers1

0

I don't know if this is the best solution, but it works:

extern template class entityx::Component<edv::Transform>;

This way it creates only one instance of that static variable.

FrameBuffer
  • 757
  • 1
  • 7
  • 26