Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix "address not mapped to object" crash #54

Merged
merged 6 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Flecs.NET.Codegen/Generators/BindingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static string GenerateFunctions(int i)
internal static void {{callback}}(ecs_iter_t* iter)
{
{{(Generator.GetCallbackIsRun(callback) ? "RunContext" : "IteratorContext")}}* context = ({{(Generator.GetCallbackIsRun(callback) ? "RunContext" : "IteratorContext")}}*)iter->{{(Generator.GetCallbackIsRun(callback) ? "run_ctx" : "callback_ctx")}};
Invoker.{{Generator.GetInvokerName(callback)}}(iter, ({{Generator.GetCallbackType(callback, i)}}){{(Generator.GetCallbackIsDelegate(callback) ? "context->Callback.GcHandle.Target!" : "context->Callback.Pointer")}});
Invoker.{{Generator.GetInvokerName(callback)}}(iter, ({{Generator.GetCallbackType(callback, i)}}){{(Generator.GetCallbackIsDelegate(callback) ? "context->Callback.Delegate.Target!" : "context->Callback.Pointer")}});
}
""");

Expand All @@ -48,7 +48,7 @@ internal static unsafe partial class Functions<{{Generator.TypeParameters[i]}}>
public static string GeneratePointers(int i)
{
IEnumerable<string> pointers = Generator.CallbacksRunAndIterAndEach.Select((Callback callback) => $$"""
internal static readonly IntPtr {{callback}} = (IntPtr)(delegate* <ecs_iter_t*, void>)&Functions<{{Generator.TypeParameters[i]}}>.{{callback}};
internal static readonly nint {{callback}} = (nint)(delegate* <ecs_iter_t*, void>)&Functions<{{Generator.TypeParameters[i]}}>.{{callback}};
""");

return $$"""
Expand Down
2 changes: 1 addition & 1 deletion src/Flecs.NET.Codegen/Generators/NodeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static string GenerateExtensions(Type builderType, Type returnType, int i
{
{{Generator.GetTypeName(Type.TypeHelper, i)}}.AssertReferenceTypes({{(Generator.GetCallbackIsUnmanaged(callback) ? "false" : "true")}});
{{Generator.GetTypeName(Type.TypeHelper, i)}}.AssertSparseTypes(World, {{(Generator.GetCallbackIsIter(callback) ? "false" : "true")}});
return {{(Generator.GetCallbackIsRun(callback) ? "SetRun" : "SetCallback")}}({{(Generator.GetCallbackIsDelegate(callback) ? string.Empty : "(IntPtr)")}}callback, Pointers<{{Generator.TypeParameters[i]}}>.{{callback}}).Build();
return {{(Generator.GetCallbackIsRun(callback) ? "SetRun" : "SetCallback")}}({{(Generator.GetCallbackIsDelegate(callback) ? string.Empty : "(nint)")}}callback, Pointers<{{Generator.TypeParameters[i]}}>.{{callback}}).Build();
}
""");

Expand Down
8 changes: 4 additions & 4 deletions src/Flecs.NET.Codegen/Generators/ObserverBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,25 +147,25 @@ public void Dispose()
return ref this;
}

private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetCallback<T>(T callback, IntPtr invoker) where T : Delegate
private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetCallback<T>(T callback, nint invoker) where T : Delegate
{
_observerBuilder.SetCallback(callback, invoker);
return ref this;
}

private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetCallback(IntPtr callback, IntPtr invoker)
private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetCallback(nint callback, nint invoker)
{
_observerBuilder.SetCallback(callback, invoker);
return ref this;
}

private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetRun<T>(T callback, IntPtr invoker) where T : Delegate
private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetRun<T>(T callback, nint invoker) where T : Delegate
{
_observerBuilder.SetRun(callback, invoker);
return ref this;
}

private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetRun(IntPtr callback, IntPtr invoker)
private ref {{Generator.GetTypeName(Type.ObserverBuilder, i)}} SetRun(nint callback, nint invoker)
{
_observerBuilder.SetRun(callback, invoker);
return ref this;
Expand Down
6 changes: 3 additions & 3 deletions src/Flecs.NET.Codegen/Generators/Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ public bool Changed()
return _query.GroupInfo(groupId);
}

/// <inheritdoc cref="Query.GroupCtx(ulong)"/>
public void* GroupCtx(ulong groupId)
/// <inheritdoc cref="Query.GroupCtx{T}(ulong)"/>
public ref T GroupCtx<T>(ulong group)
{
return _query.GroupCtx(groupId);
return ref _query.GroupCtx<T>(group);
}

/// <inheritdoc cref="Query.EachTerm(Ecs.TermCallback)"/>
Expand Down
91 changes: 56 additions & 35 deletions src/Flecs.NET.Codegen/Generators/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,17 +1052,17 @@ public unsafe partial struct {{Generator.GetTypeName(type, i)}}
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.OrderBy(ulong, Ecs.OrderByAction)"/>
public ref {{Generator.GetTypeName(type, i)}} OrderBy(ulong component, Ecs.OrderByAction compare)
/// <inheritdoc cref="Core.QueryBuilder.OrderBy(ulong, Ecs.OrderByCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} OrderBy(ulong component, Ecs.OrderByCallback callback)
{
Ecs.GetQueryBuilder(ref this).OrderBy(component, compare);
Ecs.GetQueryBuilder(ref this).OrderBy(component, callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.OrderBy{T}(Ecs.OrderByAction)"/>
public ref {{Generator.GetTypeName(type, i)}} OrderBy<T>(Ecs.OrderByAction compare)
/// <inheritdoc cref="Core.QueryBuilder.OrderBy{T}(Ecs.OrderByCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} OrderBy<T>(Ecs.OrderByCallback callback)
{
Ecs.GetQueryBuilder(ref this).OrderBy<T>(compare);
Ecs.GetQueryBuilder(ref this).OrderBy<T>(callback);
return ref this;
}

Expand All @@ -1072,6 +1072,20 @@ public unsafe partial struct {{Generator.GetTypeName(type, i)}}
Ecs.GetQueryBuilder(ref this).GroupBy(component);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.GroupBy(ulong, Ecs.GroupByCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy(ulong component, Ecs.GroupByCallback callback)
{
Ecs.GetQueryBuilder(ref this).GroupBy(component, callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.GroupBy{TContext}(ulong, Ecs.GroupByCallback{TContext})"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy<TContext>(ulong component, Ecs.GroupByCallback<TContext> callback)
{
Ecs.GetQueryBuilder(ref this).GroupBy(component, callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.GroupBy{T}()"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy<T>()
Expand All @@ -1080,59 +1094,66 @@ public unsafe partial struct {{Generator.GetTypeName(type, i)}}
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.GroupBy(ulong, Ecs.GroupByAction)"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy(ulong component, Ecs.GroupByAction callback)
/// <inheritdoc cref="Core.QueryBuilder.GroupBy{T}(Ecs.GroupByCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy<T>(Ecs.GroupByCallback callback)
{
Ecs.GetQueryBuilder(ref this).GroupBy(component, callback);
Ecs.GetQueryBuilder(ref this).GroupBy<T>(callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.GroupBy{T}(Ecs.GroupByAction)"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy<T>(Ecs.GroupByAction callback)
/// <inheritdoc cref="Core.QueryBuilder.GroupBy{T, TContext}(Ecs.GroupByCallback{TContext})"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy<T, TContext>(Ecs.GroupByCallback<TContext> callback)
{
Ecs.GetQueryBuilder(ref this).GroupBy<T>(callback);
Ecs.GetQueryBuilder(ref this).GroupBy<T, TContext>(callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.GroupBy(ulong, Ecs.GroupByCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy(ulong component, Ecs.GroupByCallback callback)
/// <inheritdoc cref="Core.QueryBuilder.GroupByCtx{T}(T)"/>
public ref {{Generator.GetTypeName(type, i)}} GroupByCtx<T>(T value)
{
Ecs.GetQueryBuilder(ref this).GroupBy(component, callback);
Ecs.GetQueryBuilder(ref this).GroupByCtx(value);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.GroupBy{T}(Ecs.GroupByCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} GroupBy<T>(Ecs.GroupByCallback callback)
/// <inheritdoc cref="Core.QueryBuilder.GroupByCtx{T}(T, Ecs.UserContextFinish{T})"/>
public ref {{Generator.GetTypeName(type, i)}} GroupByCtx<T>(T value, Ecs.UserContextFinish<T> callback)
{
Ecs.GetQueryBuilder(ref this).GroupBy<T>(callback);
Ecs.GetQueryBuilder(ref this).GroupByCtx(value, callback);
return ref this;
}

///
public ref {{Generator.GetTypeName(type, i)}} GroupByCtx(void* ctx, Ecs.ContextFree contextFree)
/// <inheritdoc cref="Core.QueryBuilder.GroupByCtx{T}(T, Ecs.UserContextFinish{T})"/>
public ref {{Generator.GetTypeName(type, i)}} GroupByCtx<T>(T value, delegate*<ref T, void> callback)
{
Ecs.GetQueryBuilder(ref this).GroupByCtx(ctx, contextFree);
Ecs.GetQueryBuilder(ref this).GroupByCtx(value, callback);
return ref this;
}

///
public ref {{Generator.GetTypeName(type, i)}} GroupByCtx(void* ctx)
/// <inheritdoc cref="Core.QueryBuilder.OnGroupCreate(Ecs.GroupCreateCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} OnGroupCreate(Ecs.GroupCreateCallback callback)
{
Ecs.GetQueryBuilder(ref this).GroupByCtx(ctx);
Ecs.GetQueryBuilder(ref this).OnGroupCreate(callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.OnGroupCreate(Ecs.GroupCreateAction)"/>
public ref {{Generator.GetTypeName(type, i)}} OnGroupCreate(Ecs.GroupCreateAction onGroupCreate)
/// <inheritdoc cref="Core.QueryBuilder.OnGroupCreate{T}(Ecs.GroupCreateCallback{T})"/>
public ref {{Generator.GetTypeName(type, i)}} OnGroupCreate<T>(Ecs.GroupCreateCallback<T> callback)
{
Ecs.GetQueryBuilder(ref this).OnGroupCreate(onGroupCreate);
Ecs.GetQueryBuilder(ref this).OnGroupCreate(callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.OnGroupDelete(Ecs.GroupDeleteAction)"/>
public ref {{Generator.GetTypeName(type, i)}} OnGroupDelete(Ecs.GroupDeleteAction onGroupDelete)
/// <inheritdoc cref="Core.QueryBuilder.OnGroupDelete(Ecs.GroupDeleteCallback)"/>
public ref {{Generator.GetTypeName(type, i)}} OnGroupDelete(Ecs.GroupDeleteCallback callback)
{
Ecs.GetQueryBuilder(ref this).OnGroupDelete(callback);
return ref this;
}

/// <inheritdoc cref="Core.QueryBuilder.OnGroupDelete{T}(Ecs.GroupDeleteCallback{T})"/>
public ref {{Generator.GetTypeName(type, i)}} OnGroupDelete<T>(Ecs.GroupDeleteCallback<T> callback)
{
Ecs.GetQueryBuilder(ref this).OnGroupDelete(onGroupDelete);
Ecs.GetQueryBuilder(ref this).OnGroupDelete(callback);
return ref this;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/Flecs.NET.Codegen/Generators/SystemBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,25 +196,25 @@ public void Dispose()
return ref this;
}

internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetCallback<T>(T callback, IntPtr invoker) where T : Delegate
internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetCallback<T>(T callback, nint invoker) where T : Delegate
{
_systemBuilder.SetCallback(callback, invoker);
return ref this;
}

internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetCallback(IntPtr callback, IntPtr invoker)
internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetCallback(nint callback, nint invoker)
{
_systemBuilder.SetCallback(callback, invoker);
return ref this;
}

internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetRun<T>(T callback, IntPtr invoker) where T : Delegate
internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetRun<T>(T callback, nint invoker) where T : Delegate
{
_systemBuilder.SetRun(callback, invoker);
return ref this;
}

internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetRun(IntPtr callback, IntPtr invoker)
internal ref {{Generator.GetTypeName(Type.SystemBuilder, i)}} SetRun(nint callback, nint invoker)
{
_systemBuilder.SetRun(callback, invoker);
return ref this;
Expand Down
36 changes: 12 additions & 24 deletions src/Flecs.NET.Examples/Queries/GroupByCallbacks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,20 @@ public static void Main()
// Grouped query
using Query<Position> q = world.QueryBuilder<Position>()
.GroupBy<Group>()
// Callback invoked when a new group is created
.OnGroupCreate((
flecs.ecs_world_t* world,
ulong id, // id of the group that was created
void* groupByArg) => // group_by_ctx parameter in ecs_query_desc_t struct
// Callback invoked when a new group is created. Including the third "out T" parameter
// allows you to provide a user context.
.OnGroupCreate((World world, ulong id, out GroupCtx ctx) =>
{
World w = new(world);
Console.WriteLine($"Group {w.Entity(id)} created");
Console.WriteLine($"Group {world.Entity(id)} created");

// Return data that will be associated with the group
GroupCtx* ctx = (GroupCtx*)NativeMemory.AllocZeroed((nuint)sizeof(GroupCtx));
ctx->Counter = ++groupCounter;
return ctx;
// Set data that will be associated with the group
ctx = new GroupCtx(++groupCounter);
})
// Callback invoked when a group is deleted
.OnGroupDelete((
flecs.ecs_world_t* world,
ulong id, // id of the group that was deleted
void* ctx, // group context
void* groupByArg) => // group_by_ctx parameter in ecs_query_desc_t struct
// Callback invoked when a group is deleted. Including the third "ref T" parameter
// provides access to the user context object.
.OnGroupDelete((World world, ulong id, ref GroupCtx ctx) =>
{
World w = new(world);
Console.WriteLine($"Group {w.Entity(id)} deleted");

// Free data associated with group
NativeMemory.Free(ctx);
Console.WriteLine($"Group {world.Entity(id)} deleted");
})
.Build();

Expand Down Expand Up @@ -109,10 +97,10 @@ public static void Main()
Field<Position> p = it.Field<Position>(0);

Entity group = it.World().Entity(it.GroupId());
GroupCtx* ctx = (GroupCtx*)q.GroupCtx(group);
ref GroupCtx ctx = ref it.Query().GroupCtx<GroupCtx>(group);

Console.WriteLine($" - Group {group.Path()}: table [{it.Table().Str()}]");
Console.WriteLine($" Counter: {ctx->Counter}");
Console.WriteLine($" Counter: {ctx.Counter}");

foreach (int i in it)
Console.WriteLine($" ({p[i].X}, {p[i].Y})");
Expand Down
2 changes: 1 addition & 1 deletion src/Flecs.NET.Examples/Queries/GroupByCustom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static void Main()
});
}

private static ulong GroupByRelation(World world, Table table, Entity id)
private static ulong GroupByRelation(World world, Table table, ulong id)
{
if (table.Search(id, Ecs.Wildcard, out Id match) != -1)
return match.Second();
Expand Down
20 changes: 10 additions & 10 deletions src/Flecs.NET.Tests/CSharp/Core/QueryBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ private void GroupBy()
world.Component<Tag0>();
world.Component<Tag1>();
world.Component<Tag2>();
world.Component<Tag23>();
world.Component<Tag3>();

using Query q = world.QueryBuilder()
.With<Tag23>()
.GroupBy<Tag23>(GroupByFirstId)
.With<Tag3>()
.GroupBy<Tag3>(GroupByFirstId)
.Build();

using Query qReverse = world.QueryBuilder()
.With<Tag23>()
.GroupBy<Tag23>(GroupByFirstIdNegated)
.With<Tag3>()
.GroupBy<Tag3>(GroupByFirstIdNegated)
.Build();

Entity e3 = world.Entity().Add<Tag23>().Add<Tag2>();
Entity e2 = world.Entity().Add<Tag23>().Add<Tag1>();
Entity e1 = world.Entity().Add<Tag23>().Add<Tag0>();
Entity e3 = world.Entity().Add<Tag3>().Add<Tag2>();
Entity e2 = world.Entity().Add<Tag3>().Add<Tag1>();
Entity e1 = world.Entity().Add<Tag3>().Add<Tag0>();

int count = 0;
q.Iter((Iter it) =>
Expand Down Expand Up @@ -70,13 +70,13 @@ private void GroupBy()

return;

static ulong GroupByFirstId(World world, Table table, Entity id)
static ulong GroupByFirstId(World world, Table table, ulong id)
{
Types type = table.Type();
return type.Get(0);
}

static ulong GroupByFirstIdNegated(World world, Table table, Entity id)
static ulong GroupByFirstIdNegated(World world, Table table, ulong id)
{
return ~GroupByFirstId(world, table, id);
}
Expand Down
28 changes: 28 additions & 0 deletions src/Flecs.NET.Tests/CSharp/Core/QueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -985,4 +985,32 @@ private void EachSparseSharedManaged()
Assert.Equal(30, c3.Value);
});
}

[Fact]
private void GroupByCtx()
{
using World world = World.Create();

Entity rel = world.Entity();

world.Entity()
.Add<Position>()
.Add(rel, world.Entity());

using Query query = world.QueryBuilder()
.With<Position>()
.GroupByCtx(10, static (ref int groupByCtx) =>
{
Assert.Equal(20, groupByCtx);
})
.GroupBy(rel, static (World _, Table _, ulong _, ref int groupByCtx) =>
{
Assert.Equal(10, groupByCtx);
groupByCtx = 20;
return 0;
})
.Build();

query.Each((Iter _, int _) => { });
}
}
Loading
Loading