Comments (7)
@copygirl not quite, you can actually create runtime components, according to this example:
This is quite useful for interoperating with scripting, or allowing the user to create components with scripting, which is what I am doing.
With the following excerpt, you will see that the size of this component is 24.
auto comp = ecs.component("mycomp");
comp.member(flecs::String, "text"); // 8 bytes
comp.member(flecs::U32, "some_number"); // 4 bytes
comp.member(flecs::Bool, "the_bool"); // 4 bytes
comp.member(flecs::U64, "big_uint"); // 8 bytes
std::cout << "size=" << comp.get<flecs::Component>()->size << std::endl;
Note that once a component has an entity that uses the component, no further calls to member()
are allowed. This makes sense, since there are tables and columns created of a specific size already.
All the function does is create an entity representing the member information and add it to the component entity (see here)
You have to take into account there are hooks/observers watching <Member>
being set, for example this one that actually do the job of creating the component.
So yes, it is possible to create runtime components from scratch, as well as add reflection information to existing c++ structs. This is incredibly powerful :-)
My problem is that members of type flecs::String
(that store as a pointer to the actual string) are not freed when the component is destroyed.
from flecs.
edit: I was corrected.
Correct me if I'm wrong but I believe the point of the member()
function is to create reflection information for an already existing member on a component (such as a field on a struct). All the function does is create an entity representing the member information and add it to the component entity (see here). What you're doing is registering a tag, a component with no size. It isn't resized to contain any more information, to fit the string pointer.
You can create a component at runtime with a runtime-known size, though I'm not familiar with the C++ API, so I only know of the ecs_component_init
function where you provide size and alignment manually. If you're allocating data on components you'll have to implement the correct component hooks to copy and free it appropriately yourself however.
from flecs.
Alright, I stand corrected.
My problem is that members of type
flecs::String
(that store as a pointer to the actual string) are not freed when the component is destroyed.
Does the type guarantee a lifetime for the string that's exactly as long as the component's? Because a string could be allocated with the lifetime of the program, come from static program memory, or be reused for multiple components, in which case automatic freeing would not be what you want.
I'm unsure if it can be used on a runtime component, nor if it's the right choice, but I wonder if an on_remove
hook would be the right thing to use.
from flecs.
on_remove
hook is what I will have to use to fix it on my side without having to touch Flecs.
The reason I think this is a bug is that the API that allows you to write a string via reflection does in fact free the previous string that may be already there. This means that the lifetime management of the string living inside the component instance is not the user's responsibility.
So, in the typical example:
auto comp = ecs.component("mycomp");
comp.member(flecs::String, "text");
flecs::entity e = ecs.entity();
e.add(comp);
void *ptr = e.get_mut(comp);
flecs::cursor cur(ecs, comp, ptr);
cur.push();
cur.member("text");
cur.set_string("hola");
cur.pop();
When you do cur.set_string("hola");
, the "meta" addon first frees the string at the corresponding offset, then allocates a new char* pointer to a copy of the passed string ("hola"). Since the first time you call, everything is set to 0
the first free
does nothing. The component instance now contains a pointer to a copy of "hola".
If you then do the following:
cur.push();
cur.member("text");
cur.set_string("adiós");
cur.pop();
the pointer to "hola" would be freed and then replaced with a new pointer to a copy of "adiós".
The relevant code is here.
Because a string could be allocated with the lifetime of the program, come from static program memory, or be reused for multiple components, in which case automatic freeing would not be what you want.
Using the cursor API you cannot set the pointer directly. When you set a string, it copies your string and keeps ownership of that pointer.
Therefore, the meta addon is managing the memory related to strings, it is just not freeing it once the component instance is destroyed: I was expecting that it would iterate all fields with a cursor and free all non-primitive types and opaques.
from flecs.
Yep, this is a known current limitation of runtime components. What needs to happen is that the meta addon needs to register a generic destructor for freeing runtime components.
This is not very difficult to do, I'll try to take a look at this asap.
from flecs.
Related Issues (20)
- observer loss event HOT 2
- [Question] Best way to share a component between differents entities HOT 3
- README link is broken HOT 1
- Compilation failed with errors when declaring 'free' as a macro. HOT 1
- Explorer hierarchy incomplete HOT 6
- free(): invalid pointer when using sorted query with std::list HOT 1
- Bug or question - HOT 1
- Lockstep support, or deterministic calculations. HOT 7
- filter_builder() assert fail, when use term().or_() HOT 2
- Queries with Or terms and wildcard terms cause internal error HOT 1
- entity::set(T*) writes garbage HOT 1
- ECS crash after conditionally adding to an entity when using Explorer HOT 7
- flecs crashes at startup when using clang built from git
- I get exception errors in ms visual studio 2019 before the main function HOT 7
- Unintuitive behavior of setting entity names as numbers HOT 4
- Enabling or disabling a component between defer_suspend and defer_resume keeps the world deferred after progress HOT 2
- World destruction with symmetric relationship and child causes assertion HOT 4
- Add flecs.c and flecs.h as download artefacts for releases HOT 3
- ecs_set() doesn't work C HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flecs.