// --------------------------------------------------------------------------------------------------------------------
//
// 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.Linq;
using System.Runtime.InteropServices;
using System.Text;
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));
}
///
/// Reads the given native UTF-8 string.
///
/// The pointer to the string.
/// The resulting string.
public static string ReadUtf8Ptr(IntPtr stringPtr)
{
var data = new List();
var ptr = stringPtr;
var offset = 0;
while (true)
{
byte ch = Marshal.ReadByte(ptr, offset++);
if (ch == 0)
{
break;
}
data.Add(ch);
}
return Encoding.UTF8.GetString(data.ToArray());
}
///
/// Creates a pointer to a UTF-8 null-terminated string.
///
/// The string to encode.
public static IntPtr CreateUtf8Ptr(string str)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);
IntPtr stringPtr = Marshal.AllocHGlobal(bytes.Length + 1);
var offset = 0;
foreach (byte b in bytes)
{
Marshal.WriteByte(stringPtr, offset, b);
offset++;
}
Marshal.WriteByte(stringPtr, offset, 0);
return stringPtr;
}
///
/// 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 { items = nativeListInternal, items_alloc = capacity, 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
{
items = nativeListInternal,
items_alloc = list.Count,
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
{
items = nativeListInternal,
items_alloc = list.Count,
items_count = list.Count
};
IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s)));
Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false);
returnList.ListPtr = nativeListStructPtr;
return returnList;
}
///
/// Reads in a list of objects given an interator and a conversion function.
///
/// The type of the struct given by the iterator.
/// The object type to convert to.
/// The iterator to use to build the list.
/// The converter to convert from the struct to the object.
/// The list of objects.
public static List GetListFromIterator(Func iterator, Func converter)
{
return ReadStructureListFromIterator(iterator).Select(converter).ToList();
}
///
/// Reads in a list of structs given an iterator.
///
/// The type of the struct.
/// The iterator to use to build the list.
/// The list of structs.
public static List ReadStructureListFromIterator(Func iterator)
{
var structureList = new List();
IntPtr current = IntPtr.Zero;
current = iterator(current);
while (current != IntPtr.Zero)
{
T encoder = ReadStructure(current);
structureList.Add(encoder);
current = iterator(current);
}
return structureList;
}
///
/// 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);
}
}
}
}