diff --git a/src/cscore/Natives/CsEnumPropertyArrayMarshaller.cs b/src/cscore/Natives/CsEnumPropertyArrayMarshaller.cs deleted file mode 100644 index 4901b422..00000000 --- a/src/cscore/Natives/CsEnumPropertyArrayMarshaller.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Runtime.InteropServices.Marshalling; -using CsCore.Natives; -using WPIUtil.Marshal; - -namespace CsCore; - -public class CsEnumPropertyStringFree : INullTerminatedStringFree -{ - public static unsafe void FreeString(byte* ptr) - { - } -} - -[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedOut, typeof(CsEnumPropertyArrayMarshaller<,>))] -[ContiguousCollectionMarshaller] -public unsafe ref struct CsEnumPropertyArrayMarshaller where TUnmanagedElement : unmanaged -{ - private TUnmanagedElement* unmanagedStorage; - private int? length; - private T[]? managedStorage; - - public CsEnumPropertyArrayMarshaller() - { - if (typeof(TUnmanagedElement) != typeof(byte*)) - { - throw new InvalidOperationException("Target can only be byte*"); - } - } - - public ReadOnlySpan GetUnmanagedValuesSource(int numElements) - { - length = numElements; - return new ReadOnlySpan(unmanagedStorage, numElements); - } - - public Span GetManagedValuesDestination(int numElements) - { - length = numElements; - managedStorage = new T[numElements]; - return managedStorage; - } - - public readonly void Free() - { - if (unmanagedStorage != null && length.HasValue) - { - CsNative.FreeEnumPropertyChoices((byte**)unmanagedStorage, length.Value); - } - } - - public void FromUnmanaged(TUnmanagedElement* unmanaged) - { - unmanagedStorage = unmanaged; - } - - public readonly T[] ToManaged() - { - return managedStorage!; - } -} diff --git a/src/cscore/Natives/CsNative.Free.cs b/src/cscore/Natives/CsNative.Free.cs index 640aa205..f1cdc522 100644 --- a/src/cscore/Natives/CsNative.Free.cs +++ b/src/cscore/Natives/CsNative.Free.cs @@ -17,10 +17,6 @@ public static unsafe partial class CsNative [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial void ReleaseEnumeratedSinks(int* sinks, int count); - [LibraryImport("cscore", EntryPoint = "CS_FreeString")] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static partial void FreeString(byte* str); - [LibraryImport("cscore", EntryPoint = "CS_FreeEnumPropertyChoices")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial void FreeEnumPropertyChoices(byte** choices, int count); diff --git a/src/cscore/Natives/CsStringFree.cs b/src/cscore/Natives/CsStringFree.cs deleted file mode 100644 index 24a01687..00000000 --- a/src/cscore/Natives/CsStringFree.cs +++ /dev/null @@ -1,12 +0,0 @@ -using CsCore.Natives; -using WPIUtil.Marshal; - -namespace CsCore; - -public class CsStringFree : INullTerminatedStringFree -{ - public static unsafe void FreeString(byte* ptr) - { - CsNative.FreeString(ptr); - } -} diff --git a/src/cscore/Natives/HttpCameraUrlsArrayMarshaller.cs b/src/cscore/Natives/HttpCameraUrlsArrayMarshaller.cs deleted file mode 100644 index 1ed87bf8..00000000 --- a/src/cscore/Natives/HttpCameraUrlsArrayMarshaller.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Runtime.InteropServices.Marshalling; -using CsCore.Natives; -using WPIUtil.Marshal; - -namespace CsCore; - -public class HttpCameraUrlsStringFree : INullTerminatedStringFree -{ - public static unsafe void FreeString(byte* ptr) - { - } -} - -[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedOut, typeof(HttpCameraUrlsArrayMarshaller<,>))] -[ContiguousCollectionMarshaller] -public unsafe ref struct HttpCameraUrlsArrayMarshaller where TUnmanagedElement : unmanaged -{ - private TUnmanagedElement* unmanagedStorage; - private int? length; - private T[]? managedStorage; - - public HttpCameraUrlsArrayMarshaller() - { - if (typeof(TUnmanagedElement) != typeof(byte*)) - { - throw new InvalidOperationException("Target can only be byte*"); - } - } - - public ReadOnlySpan GetUnmanagedValuesSource(int numElements) - { - length = numElements; - return new ReadOnlySpan(unmanagedStorage, numElements); - } - - public Span GetManagedValuesDestination(int numElements) - { - length = numElements; - managedStorage = new T[numElements]; - return managedStorage; - } - - public readonly void Free() - { - if (unmanagedStorage != null && length.HasValue) - { - CsNative.FreeHttpCameraUrls((byte**)unmanagedStorage, length.Value); - } - } - - public void FromUnmanaged(TUnmanagedElement* unmanaged) - { - unmanagedStorage = unmanaged; - } - - public readonly T[] ToManaged() - { - return managedStorage!; - } -} diff --git a/src/cscore/Natives/NetworkInterfacesArrayMarshaller.cs b/src/cscore/Natives/NetworkInterfacesArrayMarshaller.cs deleted file mode 100644 index bf5ca258..00000000 --- a/src/cscore/Natives/NetworkInterfacesArrayMarshaller.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Runtime.InteropServices.Marshalling; -using CsCore.Natives; -using WPIUtil.Marshal; - -namespace CsCore; - -public class NetworkInterfacesStringFree : INullTerminatedStringFree -{ - public static unsafe void FreeString(byte* ptr) - { - } -} - -[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedOut, typeof(NetworkInterfacesArrayMarshaller<,>))] -[ContiguousCollectionMarshaller] -public unsafe ref struct NetworkInterfacesArrayMarshaller where TUnmanagedElement : unmanaged -{ - private TUnmanagedElement* unmanagedStorage; - private int? length; - private T[]? managedStorage; - - public NetworkInterfacesArrayMarshaller() - { - if (typeof(TUnmanagedElement) != typeof(byte*)) - { - throw new InvalidOperationException("Target can only be byte*"); - } - } - - public ReadOnlySpan GetUnmanagedValuesSource(int numElements) - { - length = numElements; - return new ReadOnlySpan(unmanagedStorage, numElements); - } - - public Span GetManagedValuesDestination(int numElements) - { - length = numElements; - managedStorage = new T[numElements]; - return managedStorage; - } - - public readonly void Free() - { - if (unmanagedStorage != null && length.HasValue) - { - CsNative.FreeEnumPropertyChoices((byte**)unmanagedStorage, length.Value); - } - } - - public void FromUnmanaged(TUnmanagedElement* unmanaged) - { - unmanagedStorage = unmanaged; - } - - public readonly T[] ToManaged() - { - return managedStorage!; - } -} diff --git a/src/hal/Assembly.cs b/src/hal/Assembly.cs new file mode 100644 index 00000000..7af39553 --- /dev/null +++ b/src/hal/Assembly.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: DisableRuntimeMarshalling] diff --git a/src/hal/JoystickDescriptor.cs b/src/hal/JoystickDescriptor.cs index 499490e0..b1314eea 100644 --- a/src/hal/JoystickDescriptor.cs +++ b/src/hal/JoystickDescriptor.cs @@ -36,7 +36,7 @@ public readonly unsafe string FromNullTerminatedString() ReadOnlySpan thisSpan = this; fixed (byte* b = thisSpan) { - return Marshal.PtrToStringUTF8((nint)b)!; + return System.Runtime.InteropServices.Marshal.PtrToStringUTF8((nint)b)!; } } } diff --git a/src/wpiutil/Marshal/INullTerminatedStringFree.cs b/src/hal/Marshal/INullTerminatedStringFree.cs similarity index 82% rename from src/wpiutil/Marshal/INullTerminatedStringFree.cs rename to src/hal/Marshal/INullTerminatedStringFree.cs index c09b5460..12144ede 100644 --- a/src/wpiutil/Marshal/INullTerminatedStringFree.cs +++ b/src/hal/Marshal/INullTerminatedStringFree.cs @@ -1,4 +1,4 @@ -namespace WPIUtil.Marshal; +namespace WPIHal.Marshal; public interface INullTerminatedStringFree where T : unmanaged { diff --git a/src/wpiutil/Marshal/NoFreeNullTerminatedStringFree.cs b/src/hal/Marshal/NoFreeNullTerminatedStringFree.cs similarity index 84% rename from src/wpiutil/Marshal/NoFreeNullTerminatedStringFree.cs rename to src/hal/Marshal/NoFreeNullTerminatedStringFree.cs index 92b343a7..b4e8ff30 100644 --- a/src/wpiutil/Marshal/NoFreeNullTerminatedStringFree.cs +++ b/src/hal/Marshal/NoFreeNullTerminatedStringFree.cs @@ -1,4 +1,4 @@ -namespace WPIUtil.Marshal; +namespace WPIHal.Marshal; public class NoFreeNullTerminatedStringFree : INullTerminatedStringFree { diff --git a/src/wpiutil/Marshal/NullTerminatedStringMarshaller.cs b/src/hal/Marshal/NullTerminatedStringMarshaller.cs similarity index 93% rename from src/wpiutil/Marshal/NullTerminatedStringMarshaller.cs rename to src/hal/Marshal/NullTerminatedStringMarshaller.cs index fd6ec94c..f93d74ec 100644 --- a/src/wpiutil/Marshal/NullTerminatedStringMarshaller.cs +++ b/src/hal/Marshal/NullTerminatedStringMarshaller.cs @@ -1,7 +1,8 @@ using System; using System.Runtime.InteropServices.Marshalling; +using WPIUtil.Marshal; -namespace WPIUtil.Marshal; +namespace WPIHal.Marshal; [CustomMarshaller(typeof(string), MarshalMode.ManagedToUnmanagedOut, typeof(NullTerminatedStringMarshaller<>))] [CustomMarshaller(typeof(string), MarshalMode.ElementOut, typeof(NullTerminatedStringMarshaller<>))] diff --git a/src/hal/MatchInfo.cs b/src/hal/MatchInfo.cs index 5c678d4f..8b6a5a43 100644 --- a/src/hal/MatchInfo.cs +++ b/src/hal/MatchInfo.cs @@ -36,7 +36,7 @@ public readonly unsafe string FromNullTerminatedString() ReadOnlySpan thisSpan = this; fixed (byte* b = thisSpan) { - return Marshal.PtrToStringUTF8((nint)b)!; + return System.Runtime.InteropServices.Marshal.PtrToStringUTF8((nint)b)!; } } diff --git a/src/hal/Natives/HalBase.cs b/src/hal/Natives/HalBase.cs index 1b22efc2..f9241a64 100644 --- a/src/hal/Natives/HalBase.cs +++ b/src/hal/Natives/HalBase.cs @@ -2,6 +2,7 @@ using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; using WPIHal.Handles; +using WPIHal.Marshal; using WPIUtil.Marshal; namespace WPIHal.Natives; diff --git a/src/hal/Natives/HalDriverStation.cs b/src/hal/Natives/HalDriverStation.cs index c72cbba6..33c61127 100644 --- a/src/hal/Natives/HalDriverStation.cs +++ b/src/hal/Natives/HalDriverStation.cs @@ -37,12 +37,7 @@ public static partial class HalDriverStation [LibraryImport("wpiHal", EntryPoint = "HAL_GetJoystickName")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - [return: MarshalUsing(typeof(NullTerminatedStringMarshaller))] - public static partial string GetJoystickName(int joystickNum); - - [LibraryImport("wpiHal", EntryPoint = "HAL_FreeJoystickName")] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static unsafe partial void FreeJoystickName(byte* joystickName); + public static partial void GetJoystickName([MarshalUsing(typeof(WpiStringMarshaller))] out string name, int joystickNum); [LibraryImport("wpiHal", EntryPoint = "HAL_GetJoystickPOVs")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] diff --git a/src/hal/Natives/JoystickNameStringFree.cs b/src/hal/Natives/JoystickNameStringFree.cs deleted file mode 100644 index aa792fad..00000000 --- a/src/hal/Natives/JoystickNameStringFree.cs +++ /dev/null @@ -1,11 +0,0 @@ -using WPIUtil.Marshal; - -namespace WPIHal.Natives; - -public class JoystickNameStringFree : INullTerminatedStringFree -{ - public static unsafe void FreeString(byte* ptr) - { - HalDriverStation.FreeJoystickName(ptr); - } -} diff --git a/src/wpiutil/Marshal/EmptyStringMarshaller.cs b/src/wpiutil/Marshal/EmptyStringMarshaller.cs deleted file mode 100644 index d8cc84ee..00000000 --- a/src/wpiutil/Marshal/EmptyStringMarshaller.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Runtime.InteropServices.Marshalling; - -namespace WPIUtil.Marshal; - -[CustomMarshaller(typeof(string), MarshalMode.ElementOut, typeof(EmptyStringMarshaller))] -public static unsafe class EmptyStringMarshaller -{ - public static string ConvertToManaged(WpiStringMarshaller.WpiStringNative unmanaged) - { - return default!; - } - - public static WpiStringMarshaller.WpiStringNative ConvertToUnmanaged(string managed) - { - return default; - } -} diff --git a/src/wpiutil/Marshal/StringLengthPairMarshaller.cs b/src/wpiutil/Marshal/StringLengthPairMarshaller.cs deleted file mode 100644 index 06ead960..00000000 --- a/src/wpiutil/Marshal/StringLengthPairMarshaller.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -using System.Text; - -namespace WPIUtil.Marshal; - -public unsafe interface IStringLengthPair -{ - public byte* Ptr { get; set; } - public nuint Len { get; set; } -} - -[CustomMarshaller(typeof(string), MarshalMode.ElementIn, typeof(StringLengthPairMarshaller<>.PassToArray))] -public static unsafe class StringLengthPairMarshaller where T : unmanaged, IStringLengthPair -{ - public static string? ManagedConvert(T unmanaged) - { - byte* ptr = unmanaged.Ptr; - if (ptr is null) - { - return null; - } - - string? ret = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((nint)ptr, checked((int)unmanaged.Len)); - return ret; - } - - public static class PassToArray - { - public static T ConvertToUnmanaged(string? managed) - { - if (managed is null || managed.Length == 0) - { - return new T - { - Ptr = (byte*)NativeMemory.Alloc(0), - Len = 0 - }; - } - - int exactByteCount = Encoding.UTF8.GetByteCount(managed); - byte* mem = (byte*)NativeMemory.Alloc((nuint)exactByteCount); - Span buffer = new(mem, exactByteCount); - - int byteCount = Encoding.UTF8.GetBytes(managed, buffer); - return new T - { - Ptr = mem, - Len = (nuint)byteCount, - }; - } - - public static void Free(T unmanaged) - { - byte* ptr = unmanaged.Ptr; - if (ptr != null) - { - NativeMemory.Free(ptr); - } - } - - public static string ConvertToManaged(T unmanaged) - { - throw new NotSupportedException(); - } - } -}