2023-08-04 12:24:49 -04:00
|
|
|
|
namespace Vanara.InteropServices;
|
2023-02-18 21:31:48 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Functions to safely convert a memory pointer to a type.</summary>
|
|
|
|
|
public static class IntPtrConverter
|
2019-03-07 11:25:12 -05:00
|
|
|
|
{
|
2023-02-18 21:31:48 -05:00
|
|
|
|
/// <summary>Converts the specified pointer to <typeparamref name="T"/>.</summary>
|
|
|
|
|
/// <typeparam name="T">The destination type.</typeparam>
|
|
|
|
|
/// <param name="ptr">The pointer to a block of memory.</param>
|
|
|
|
|
/// <param name="sz">The size of the allocated memory block.</param>
|
|
|
|
|
/// <param name="charSet">The character set.</param>
|
|
|
|
|
/// <returns>A value of the type specified.</returns>
|
|
|
|
|
public static T? Convert<T>(this IntPtr ptr, uint sz, CharSet charSet = CharSet.Auto) => (T?)Convert(ptr, sz, typeof(T), charSet);
|
|
|
|
|
|
|
|
|
|
/// <summary>Converts the specified pointer to <typeparamref name="T"/>.</summary>
|
|
|
|
|
/// <typeparam name="T">The destination type.</typeparam>
|
|
|
|
|
/// <param name="hMem">A block of allocated memory.</param>
|
|
|
|
|
/// <param name="charSet">The character set.</param>
|
|
|
|
|
/// <returns>A value of the type specified.</returns>
|
|
|
|
|
public static T? ToType<T>(this SafeAllocatedMemoryHandle hMem, CharSet charSet = CharSet.Auto)
|
2019-03-07 11:25:12 -05:00
|
|
|
|
{
|
2023-02-18 21:31:48 -05:00
|
|
|
|
if (hMem is null) throw new ArgumentNullException(nameof(hMem));
|
|
|
|
|
hMem.Lock();
|
|
|
|
|
try { return Convert<T>(hMem.DangerousGetHandle(), hMem.Size, charSet); }
|
|
|
|
|
finally { hMem.Unlock(); }
|
|
|
|
|
}
|
2019-12-06 19:09:56 -05:00
|
|
|
|
|
2023-02-18 21:31:48 -05:00
|
|
|
|
/// <summary>Converts the specified pointer to type specified in <paramref name="destType"/>.</summary>
|
|
|
|
|
/// <param name="ptr">The pointer to a block of memory.</param>
|
|
|
|
|
/// <param name="sz">The size of the allocated memory block.</param>
|
|
|
|
|
/// <param name="destType">The destination type.</param>
|
|
|
|
|
/// <param name="charSet">The character set.</param>
|
|
|
|
|
/// <returns>A value of the type specified.</returns>
|
|
|
|
|
/// <exception cref="ArgumentException">Cannot convert a null pointer. - ptr or Cannot convert a pointer with no Size. - sz</exception>
|
|
|
|
|
/// <exception cref="NotSupportedException">Thrown if type cannot be converted from memory.</exception>
|
|
|
|
|
/// <exception cref="OutOfMemoryException"></exception>
|
|
|
|
|
public static object? Convert(this IntPtr ptr, uint sz, Type destType, CharSet charSet = CharSet.Auto)
|
|
|
|
|
{
|
|
|
|
|
if (ptr == IntPtr.Zero)
|
2019-03-07 11:25:12 -05:00
|
|
|
|
{
|
2023-02-18 21:31:48 -05:00
|
|
|
|
if (!destType.IsValueType) return null;
|
|
|
|
|
throw new NullReferenceException();
|
2019-03-07 11:25:12 -05:00
|
|
|
|
}
|
2023-02-18 21:31:48 -05:00
|
|
|
|
if (sz == 0) throw new ArgumentException("Cannot convert a pointer with no Size.", nameof(sz));
|
|
|
|
|
|
|
|
|
|
// Handle byte array and string as special cases
|
|
|
|
|
if (destType.IsArray && destType.GetElementType() == typeof(byte))
|
|
|
|
|
return ptr.ToByteArray((int)sz);
|
|
|
|
|
if (destType == typeof(string))
|
|
|
|
|
return StringHelper.GetString(ptr, charSet, sz);
|
|
|
|
|
return ptr.ToStructure(destType, sz, 0, out _);
|
2019-03-07 11:25:12 -05:00
|
|
|
|
}
|
2020-07-12 09:55:22 -04:00
|
|
|
|
}
|