From a1d749ff7fa779f3f03e0a3fe0d538a5006946b1 Mon Sep 17 00:00:00 2001 From: Martin Finkel Date: Mon, 16 Sep 2019 20:56:22 +0200 Subject: [PATCH] Core: Fix size_t C# interop ulong is not always correct for size_t marshaling. Use UIntPtr for P/Invoke and cast to uint or ulong depending on bitness. Closes https://code.videolan.org/videolan/LibVLCSharp/issues/217 --- LibVLCSharp/Shared/Helpers/MarshalUtils.cs | 50 ++++++++++++++-------- LibVLCSharp/Shared/LibVLC.cs | 10 ++--- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/LibVLCSharp/Shared/Helpers/MarshalUtils.cs b/LibVLCSharp/Shared/Helpers/MarshalUtils.cs index e34d567..d374967 100644 --- a/LibVLCSharp/Shared/Helpers/MarshalUtils.cs +++ b/LibVLCSharp/Shared/Helpers/MarshalUtils.cs @@ -209,7 +209,6 @@ namespace LibVLCSharp.Shared.Helpers /// /// Generic marshalling function to retrieve structs from libvlc by reading from unmanaged memory with offsets - /// This supports ulong libvlc signatures. /// /// Internal struct type /// publicly facing struct type @@ -220,17 +219,25 @@ namespace LibVLCSharp.Shared.Helpers /// Native libvlc call: release the array allocated with the getRef call with the given element count /// An array of publicly facing struct types internal static TU[] Retrieve(IntPtr nativeRef, ArrayLongOut getRef, Func retrieve, - Func create, Action releaseRef) + Func create, Action releaseRef) where T : struct where TU : struct { var arrayPtr = IntPtr.Zero; - ulong countLong = 0; + var countSizeT = UIntPtr.Zero; + var count = 0; try - { - countLong = getRef(nativeRef, out arrayPtr); - var count = (int)countLong; + { + countSizeT = getRef(nativeRef, out arrayPtr); + if (IntPtr.Size == 4) + { + count = Convert.ToInt32((uint)countSizeT); + } + else if (IntPtr.Size == 8) + { + count = Convert.ToInt32((ulong)countSizeT); + } if (count == 0) { @@ -258,7 +265,7 @@ namespace LibVLCSharp.Shared.Helpers { if(arrayPtr != IntPtr.Zero) { - releaseRef(arrayPtr, countLong); + releaseRef(arrayPtr, countSizeT); arrayPtr = IntPtr.Zero; } } @@ -266,7 +273,7 @@ namespace LibVLCSharp.Shared.Helpers /// /// Generic marshalling function to retrieve structs from libvlc by reading from unmanaged memory with offsets - /// This supports ulong libvlc signatures and an additional enum configuration parameter. + /// This supports an additional enum configuration parameter. /// /// Internal struct type /// publicly facing struct type @@ -279,18 +286,27 @@ namespace LibVLCSharp.Shared.Helpers /// Native libvlc call: release the array allocated with the getRef call with the given element count /// An array of publicly facing struct types internal static TU[] Retrieve(IntPtr nativeRef, TE extraParam, CategoryArrayOut getRef, Func retrieve, - Func create, Action releaseRef) + Func create, Action releaseRef) where T : struct where TU : struct where TE : Enum { var arrayPtr = IntPtr.Zero; - ulong countLong = 0; + var countSizeT = UIntPtr.Zero; + var count = 0; try - { - countLong = getRef(nativeRef, extraParam, out arrayPtr); - var count = (int)countLong; + { + countSizeT = getRef(nativeRef, extraParam, out arrayPtr); + if (IntPtr.Size == 4) + { + count = Convert.ToInt32((uint)countSizeT); + } + else if (IntPtr.Size == 8) + { + count = Convert.ToInt32((ulong)countSizeT); + } + if (count == 0) { #if NETSTANDARD1_1 || NET40 @@ -317,16 +333,16 @@ namespace LibVLCSharp.Shared.Helpers { if (arrayPtr != IntPtr.Zero) { - releaseRef(arrayPtr, countLong); + releaseRef(arrayPtr, countSizeT); arrayPtr = IntPtr.Zero; } } } // These delegates allow the definition of generic functions with [OUT] parameters - internal delegate ulong CategoryArrayOut(IntPtr nativeRef, T enumType, out IntPtr array) where T : Enum; + internal delegate UIntPtr CategoryArrayOut(IntPtr nativeRef, T enumType, out IntPtr array) where T : Enum; internal delegate uint ArrayOut(IntPtr nativeRef, out IntPtr array); - internal delegate ulong ArrayLongOut(IntPtr nativeRef, out IntPtr array); + internal delegate UIntPtr ArrayLongOut(IntPtr nativeRef, out IntPtr array); /// /// Turns an array of UTF16 C# strings to an array of pointer to UTF8 strings @@ -508,4 +524,4 @@ namespace LibVLCSharp.Shared.Helpers } public Type Type { get; private set; } } -} \ No newline at end of file +} diff --git a/LibVLCSharp/Shared/LibVLC.cs b/LibVLCSharp/Shared/LibVLC.cs index 8165c85..8c3f235 100644 --- a/LibVLCSharp/Shared/LibVLC.cs +++ b/LibVLCSharp/Shared/LibVLC.cs @@ -118,11 +118,11 @@ namespace LibVLCSharp.Shared [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_media_discoverer_list_get")] - internal static extern ulong LibVLCMediaDiscovererListGet(IntPtr libVLC, MediaDiscovererCategory category, out IntPtr pppServices); + internal static extern UIntPtr LibVLCMediaDiscovererListGet(IntPtr libVLC, MediaDiscovererCategory category, out IntPtr pppServices); [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_media_discoverer_list_release")] - internal static extern void LibVLCMediaDiscovererListRelease(IntPtr ppServices, ulong count); + internal static extern void LibVLCMediaDiscovererListRelease(IntPtr ppServices, UIntPtr count); [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_dialog_set_callbacks")] @@ -130,11 +130,11 @@ namespace LibVLCSharp.Shared [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_renderer_discoverer_list_get")] - internal static extern ulong LibVLCRendererDiscovererGetList(IntPtr libVLC, out IntPtr discovererList); + internal static extern UIntPtr LibVLCRendererDiscovererGetList(IntPtr libVLC, out IntPtr discovererList); [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_renderer_discoverer_list_release")] - internal static extern void LibVLCRendererDiscovererReleaseList(IntPtr discovererList, ulong count); + internal static extern void LibVLCRendererDiscovererReleaseList(IntPtr discovererList, UIntPtr count); [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_retain")] @@ -731,4 +731,4 @@ namespace LibVLCSharp.Shared internal delegate void LogCallback(IntPtr data, LogLevel logLevel, IntPtr logContext, IntPtr format, IntPtr args); #endregion -} \ No newline at end of file +} -- 2.22.0