// -------------------------------------------------------------------------------------------------------------------- // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // // // Helper utilities for native interop. // // -------------------------------------------------------------------------------------------------------------------- namespace HandBrake.Interop { using System; using System.Collections.Generic; using System.Runtime.InteropServices; using HandBrake.Interop.HbLib; /// /// Helper utilities for native interop. /// public static class InteropUtilities { /// /// Reads the given native structure pointer. /// /// The type to convert the structure to. /// The pointer to the native structure. /// The converted structure. public static T ReadStructure(IntPtr structPtr) { return (T)Marshal.PtrToStructure(structPtr, typeof(T)); } /// /// Converts the given native HandBrake list to a managed list. /// /// The type of structure in the list. /// The pointer to the native list. /// The converted managed list. public static List ToList(this IntPtr listPtr) { List returnList = new List(); hb_list_s itemList = ReadStructure(listPtr); for (int i = 0; i < itemList.items_count; i++) { IntPtr itemPtr = Marshal.ReadIntPtr(itemList.items, i * Marshal.SizeOf(typeof(IntPtr))); returnList.Add(ReadStructure(itemPtr)); } return returnList; } /// /// Converts the HB list to a managed list of pointers. /// /// The list to convert. /// The managed list of pointers. public static List ToIntPtrList(this IntPtr listPtr) { var returnList = new List(); hb_list_s itemList = ReadStructure(listPtr); for (int i = 0; i < itemList.items_count; i++) { IntPtr itemPtr = Marshal.ReadIntPtr(itemList.items, i * Marshal.SizeOf(typeof(IntPtr))); returnList.Add(itemPtr); } return returnList; } /// /// Converts the given native array to a managed collection. /// /// The type of item in the list. /// The pointer to the array. /// The number of items in the array. /// The converted collection. public static IEnumerable ConvertArray(IntPtr arrayPtr, int count) { IntPtr currentItem = arrayPtr; var result = new List(); for (int i = 0; i < count; i++) { T nativeEncoder = ReadStructure(currentItem); result.Add(nativeEncoder); currentItem = IntPtr.Add(currentItem, Marshal.SizeOf(typeof(T))); } return result; } /// /// Creats a new, empty native HandBrake list. /// /// The capacity of the new list. /// The new native list. public static NativeList CreateNativeList(int capacity) { NativeList returnList = new NativeList(); int intSize = Marshal.SizeOf(typeof(IntPtr)); IntPtr nativeListInternal = Marshal.AllocHGlobal(capacity * intSize); returnList.AllocatedMemory.Add(nativeListInternal); hb_list_s nativeListStruct = new hb_list_s(); nativeListStruct.items = nativeListInternal; nativeListStruct.items_alloc = capacity; nativeListStruct.items_count = 0; IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s))); Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false); returnList.ListPtr = nativeListStructPtr; return returnList; } /// /// Creates a native HandBrake list from the given managed list of pointers. /// /// The managed list to convert. /// The converted native list. public static NativeList CreateIntPtrList(List list) { NativeList returnList = new NativeList(); int intSize = Marshal.SizeOf(typeof(IntPtr)); IntPtr nativeListInternal = Marshal.AllocHGlobal(list.Count * intSize); returnList.AllocatedMemory.Add(nativeListInternal); for (int i = 0; i < list.Count; i++) { Marshal.WriteIntPtr(nativeListInternal, i * intSize, list[i]); } hb_list_s nativeListStruct = new hb_list_s(); nativeListStruct.items = nativeListInternal; nativeListStruct.items_alloc = list.Count; nativeListStruct.items_count = list.Count; IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s))); Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false); returnList.ListPtr = nativeListStructPtr; return returnList; } /// /// Creates a native HandBrake list from the given managed list of structures. /// /// The type of structures in the list. /// The managed list to convert. /// The converted native list. public static NativeList ConvertListBack(List list) { NativeList returnList = new NativeList(); int intSize = Marshal.SizeOf(typeof(IntPtr)); IntPtr nativeListInternal = Marshal.AllocHGlobal(list.Count * intSize); returnList.AllocatedMemory.Add(nativeListInternal); for (int i = 0; i < list.Count; i++) { IntPtr itemPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T))); returnList.AllocatedMemory.Add(itemPtr); Marshal.StructureToPtr(list[i], itemPtr, false); Marshal.WriteIntPtr(nativeListInternal, i * intSize, itemPtr); } hb_list_s nativeListStruct = new hb_list_s(); nativeListStruct.items = nativeListInternal; nativeListStruct.items_alloc = list.Count; nativeListStruct.items_count = list.Count; IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s))); Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false); returnList.ListPtr = nativeListStructPtr; return returnList; } /// /// Closes the given job. /// /// The pointer to the job. public static void CloseJob(IntPtr nativeJobPtr) { // Create a point to the job pointer first. IntPtr nativeJobPtrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); // Assign the new pointer to the job pointer and tell HB to clean the job up. Marshal.WriteIntPtr(nativeJobPtrPtr, nativeJobPtr); HBFunctions.hb_job_close(nativeJobPtrPtr); // Free the pointer we used. Marshal.FreeHGlobal(nativeJobPtrPtr); } /// /// Frees all the memory locations in the given list. /// /// The list of memory locations to free. public static void FreeMemory(List memoryList) { foreach (IntPtr memoryLocation in memoryList) { Marshal.FreeHGlobal(memoryLocation); } } } }