CesiumGS / CesiumGS/cesium-unity

Better handling of Generic functions in Reinterop

Open
#379 0 comments 0 reactions 0 assignees View on GitHub
reinterop
Dominant language
C#
Stars
535
Forks
132
Avg merge
6h 45m
Merged PRs (30d)
1

Description

While working on the planned 3D tiles 1.1 upgrade for metadata in Unity, I wondered if we could integrate Generics in any way to simplify the API. In particular, I thought it might be useful to have a `CesiumPropertyTableProperty.GetAs` function, to avoid the individual `GetBoolean`, `GetString`, etc. calls we have to write for every possible type.

The idea is to implement the `GetAs` on the C++ side with templating. Then, in `ConfigureReinterop`, we can list every single type of `T` that we expect to handle. Currently, Reinterop takes the generic function, and turns it into a template on the C++ side:

```
template
T GetAs(const T& value) const;
```
Then, it has a bunch of different calls matching the expected types, and it specializes the template in the .cpp file. Aside from an erroneous `#include `, it's actually possible to compile the native code with a `template GetAs` C++ implementation. However...it doesn't completely work. Unity complains on the C# about `CesiumPropertyTableProperty-generated.cs`, because it generates the partial method like so:
```
public partial T GetAs(T value)
{
unsafe
{
if (this._implementation == null || this._implementation.IsInvalid)
throw new NotImplementedException("The native implementation is missing so GetAs cannot be invoked. This may be caused by a missing call to CreateImplementation in one of your constructors, or it may be that the entire native implementation shared library is missing or out of date.");
var result = DotNet_CesiumForUnity_CesiumPropertyTableProperty_GetAs(Reinterop.ObjectHandleUtility.CreateHandle(this), _implementation, value);
return result;
}
}
```

As @kring noted:
> So the immediate problem is that it's not declared as a generic method at all.
But the bigger problem is that we can't write a single implementation of this method that works across types.

Ultimately we decided it's better to have the individual `Get___` functions for usability reasons outside of Reinterop. But a solution that @kring proposed, if we need it in the future:

>It's not totally impossible. You can use a generic class with a static field as a kind of map with C# generics.
something like:
```
class TypeMapThingo {
static int SomeValue;
}
TypeMapThingo.SomeValue = 4;
TypeMapThing.SomeValue = 5;
```
> so in this case SomeValue could be a delegate that is used to dispatch to the correct C++ function pointer.
> But that'd definitely takes some changes to Reinterop

Contributor guide

Open the contributing guide

Research direction

Start by reading ConfigureReinterop and the generated CesiumPropertyTableProperty-generated.cs method, then inspect the C++ template and specialization approach described in the issue. Before implementation, agree on whether generic dispatch is still wanted and define acceptance criteria for supported types and generated C# behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, csharp, unity
Domain
game-dev, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.