Closed felippeduran closed 5 years ago
What’s the assertion?
Thanks for the reply, @alecthomas!
The assertion says that the entity doesn’t have ComponentA
. As the Event::family()
changes between the time the dependency is created (within the shared library) and the time ComponentB
is assigned to the entity (editor code), the event notification fails and EntityX doesn’t assign ComponentA
automatically.
To be more descriptive about the code organisation, EntityX is compiled as a shared library. The engine code too, which uses the EntityX shared library, and the editor code uses both shared libraries.
Can you provide some sample code? Also are you sure the dwpendency is being added?
Hi, @alecthomas
Here's the sample code to reproduce the issue. It seems to be working properly when I compile it by hand (using clang or g++). The issue only occurs when I compile it as a XCode project/workspace, so I'm suspecting it might be related to some compiler configuration or XCode setup.
GameEngine.h:
#include "entityx/entityx.h"
struct ComponentA {
int a;
};
struct ComponentB {
int b;
};
class GameEngine : public entityx::EntityX {
public:
// explicit GameEngine();
// ~GameEngine();
void initialize();
void configure();
int start();
void update(entityx::TimeDelta dt);
};
struct DummySystem : public entityx::System<DummySystem> {
void update(entityx::EntityManager &es, entityx::EventManager &events, entityx::TimeDelta dt) override {};
};
GameEngine.cpp:
#include "Engine.h"
#include "entityx/deps/Dependencies.h"
using namespace entityx;
void GameEngine::initialize() {
systems.add<deps::Dependency<ComponentB, ComponentA>>();
systems.add<DummySystem>();
}
void GameEngine::configure() {
systems.configure();
}
main.cpp:
#include <iostream>
#include "entityx.h"
#include "Engine.h"
using namespace std;
using namespace entityx;
void setup();
GameEngine engine;
struct DummySystem2 : public entityx::System<DummySystem2> {
void update(entityx::EntityManager &es, entityx::EventManager &events, entityx::TimeDelta dt) override {};
};
int main(int argc, const char *argv[])
{
engine.initialize();
engine.systems.add<DummySystem2>();
engine.configure();
setup();
return 0;
}
void setup()
{
Entity entity = engine.entities.create();
entity.assign<ComponentB>();
printf("Entity has ComponentA: %d\n", entity.has_component<ComponentA>());
entity.component<ComponentA>()->a = 10; // This should throw an assert
}
The first two files belong to the engine and are compiled as a separate dynamic library. The third file, main.cpp
, is compiled as an executable that links to the engine library. Both binaries link to an EntityX dynamic library.
Alright, so I finally managed to reproduce the issue outside XCode and fix it within the XCode project. The whole issue is caused by the compiler flag -fvisibility-inlines-hidden
, which is enabled by default in XCode.
It seems that this flag was hiding the definition of the static variable family
from each event template implementation (and maybe system) between shared objects. In the end, the issue was not related to the family_counter
, but the family
instead (which is now pretty obvious). I've also found an explanation of this behaviour in greater detail in this stackoverflow answer.
After I changed EntityX from a static library to a dynamic one, I was expecting that it would fix all problems related to duplicate memory addresses, but that was not the case and it bugged me!
Thanks for the help anyway, @alecthomas!
Hope this thread might be useful to other people in the future!
That is great to know, thanks. It seems frankly bizarre that statics would be inlined under any circumstances...
Hi,
I'm using EntityX as a shared library for a project that consists of a common code base of a game engine, an editor an a game demo. Initially, I was using it as a static library and ran into issues related to the
System::family_counter_
being allocated into multiple addresses. Once I moved to a shared library this problem disappeared, however I'm facing another issue now.Inside the game engine initialization, which is an implementation of
entityx::EntityX
, I callsystems.add<deps::Dependency<ComponentB, ComponentA>>();
, setup my systems and then callsystems.configure()
. Then, within the editor code (which uses the shared library), I create an entity as below, but it gives me an assertion:Inspecting the issue a bit further, I found out that the
Event::family_counter
value set during the system/dependencies configuration changes when the event is created during this entity initialization.Is there something I'm doing wrong? Should EntityX work properly in this case?
Thanks in advance!