You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
C# 9 added support for native-sized integers as a drop-in replacements for IntPtr (and UIntPtr). The new native-sized intger types, nint and nuint, were added specifically to improve the experience of coding for interop scenarios, e.g. by low-level library authors, of which Silk.Net is a prime example. By changing our references to IntPtr and UIntPtr to nint and nuint respectively, consumers using C#9.0 will be pointed towards the new types and will benefit from the improvements provided.
Further, Silk.Net internal development will benefit by being less verbose.
Comments
After reviewing the implementation, the 2 new types are effectively implemented as syntatic sugar over IntPr and UIntPtr, with a new attribute NativeIntegerAttribute marking instances of the type for code compiled using C#9.0+. As such, library consumers on an older version of C# should continue to see the API as exposing IntPtr and UIntPtr and there shouldn't be any breaking changes introduced.
which assumes a 64-bit architecture, can instead be written safely as:
publicnintAdd(ninta,nintb)=>a+b;
So long as the consumer is using C#9.0+.
Note this code can be called using IntPtr's due to implicit casting, e.g.:
publicIntPtrTest(IntPtra,IntPtrb)=>Add(a,b);
Will continue to work, allowing the API to be backwards compatible.
It would be useful to introduce the change in a preview build, after initial careful testing, to see if it causes any issues for existing consumers.
Alternatives
It is also plausible to not make this change at all. Consumers can then optionally perform the casting themselves. The only downside is the reduced discoverability of the new modern types, as there shouldn't be any real performance impact of casting, for example, the following is valid:
Note, as per the proposal, the following pointer members are not exposed on the corresponding native-sized integer:
// constructors// arithmetic operators// implicit and explicit conversionspublicstaticreadonlyIntPtrZero;// use 0 insteadpublicstaticintSize{get;}// use sizeof() insteadpublicstaticIntPtrAdd(IntPtrpointer,intoffset);// use + operator insteadpublicstaticIntPtrSubtract(IntPtrpointer,intoffset);// use - operator insteadpublicintToInt32();// cast to int insteadpubliclongToInt64();// cast to long insteadpublicvoid*ToPointer();
However, implicit casting (actually there is no cast performed in reality as the implementation is syntatic sugar) comes to the rescue in most use cases, e.g.:
ninta=IntPtr.Zero;// Existing code works when assigning to nint((IntPtr)a).ToPointer();// A cast is needed here - though is is removed on compilation.
Because of these changes then any existing C#9.0 code that expects to receive a pointer from the API, but instead gets the new native-sized integer, and is using implicit typing, the code will fail to compile if they try to access any of ToInt32(), ToInt64() and ToPointer(). The fix for these is trivial, and C#9.0 is new enough that there is unlikely to be a large technical debt of code written at that lang-level.
e.g.
// Implicit typed a used to be IntPtr, but is now nintvara=APIMethodPreviousReturnedIntPtr();varb=a.ToInt32();// No longer compiles// Or direct access to return valueb=APIMethodPreviousReturnedIntPtr().ToInt32();// No longer compilesIntPtrc=APIMethodPreviousReturnedIntPtr();// Implicit 'cast'b=c.ToInt32();// Succeedsb=((IntPtr)APIMethodPreviousReturnedIntPtr()).ToInt32();// Succeeds
(Similar for out and ref parameters though these are less likely to be implicitly typed)
Conclusion
C#9.0 was only released last month, and Silk.NET 2.0 is still in preview with breaking changes. As such this is the ideal time to make the change with minimal (if any) impact. A future change would be more difficult once 2.0 goes RTM, as more production code is likely to be developed against it using C#9.0; also anyone who upgrades their existing projects to C#9.0 will experience the breaking changes at the point of upgrade. It would be much less impactful if they are doing so at the same time as upgrading to v.2.0 of the library.
Activity
thargy commentedon Dec 30, 2020
Note, as per the proposal, the following pointer members are not exposed on the corresponding native-sized integer:
However, implicit casting (actually there is no cast performed in reality as the implementation is syntatic sugar) comes to the rescue in most use cases, e.g.:
Because of these changes then any existing C#9.0 code that expects to receive a pointer from the API, but instead gets the new native-sized integer, and is using implicit typing, the code will fail to compile if they try to access any of
ToInt32(),ToInt64()andToPointer(). The fix for these is trivial, and C#9.0 is new enough that there is unlikely to be a large technical debt of code written at that lang-level.e.g.
(Similar for
outandrefparameters though these are less likely to be implicitly typed)Conclusion
C#9.0 was only released last month, and
Silk.NET 2.0is still in preview with breaking changes. As such this is the ideal time to make the change with minimal (if any) impact. A future change would be more difficult once 2.0 goes RTM, as more production code is likely to be developed against it using C#9.0; also anyone who upgrades their existing projects to C#9.0 will experience the breaking changes at the point of upgrade. It would be much less impactful if they are doing so at the same time as upgrading to v.2.0 of the library.nints and start of Vulkan Function Tables (closes #387)
This is Silk.NET 2.0 (#392)