SanderMertens / flecs

A fast entity component system (ECS) for C & C++
https://www.flecs.dev
MIT License
5.84k stars 412 forks source link

In C++ component ignores scoping resulting in a crash. #1223

Open robo-todd opened 3 days ago

robo-todd commented 3 days ago

Describe the bug I have a module in C++ that defines components during initialization. Some of the components are "inner classes" or structs inside of an outer class to make other parts of the C++ interface in my application better scoped/cleaner. This results in a crash when importing the module because it appears to be registering things with the same name (ignoring the enclosing scope) within the module scope.

To Reproduce

namespace Z { class A { struct Foo { } };

class B { struct Foo { } }; }

.... in module import function: ecs.module(); ecs.component(); // Registers component X.Foo visible in explorer. ecs.component(); // Hard crash with fatal: entity.c: 1897: X.Init (INVALID_COMPONENT_SIZE)

Expected behavior I would expect a scoped name to be resolved to a scoped name within the module for component definition.

Additional context Perhaps there is a workaround somehow, but I've run into a lot of things like this when nesting namespaces on the C++ side, etc. and it is hard to know what to expect with the scoping because the single namespace (if I don't register inner types) seems to 'just work' fine.

Flecs v3.2.11 on Ubuntu 22.04/gcc

SanderMertens commented 3 days ago

Thanks for the issue! Are you able to provide the entire code example that reproduces the problem?

robo-todd commented 2 days ago

It is part of a large codebase (hence my desire for scoping). I can try to cook up a smaller example. I did find a workaround in that I can make a component for the enclosing class and then make the component for the inner class and add it as a child of the enclosing 'component entity'. This only seems to affect registration because I can use the inner class/struct as an argument for query/system/observer, etc. and that "just works" like I would expect. So registration code in the module ends up looking like:

auto outer = ecs.component<A>();
ecs.component<A:Foo>().child_of(outer);

Then things like:

ecs.observer<A:Foo>()... work just fine.

SanderMertens commented 2 days ago

I can try to cook up a smaller example.

That would be helpful. There are many tests that verify registration of components in scopes, so I'm curious what exactly is leading to this error message.