CesiumGS / CesiumGS/cesium-unity
Better handling of Generic functions in 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
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