Tools and libraries to glue C/C++ APIs to high-level languages
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

60 lines
2.0 KiB

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace CppSharp.Runtime
{
public struct VTables
{
public Delegate[][] Methods { get; set; }
public IntPtr[] Tables { get; set; }
private ConcurrentDictionary<(short, short, int), Delegate> Specializations;
public VTables(IntPtr[] tables, Delegate[][] methods = null)
{
Tables = tables;
Methods = methods;
Specializations = null;
}
public bool IsEmpty => Tables == null;
public bool IsTransient => Methods == null;
public T GetMethodDelegate<T>(short table, int slot, short specialiation = 0) where T : Delegate
{
if (specialiation == 0 && !IsTransient)
{
var method = Methods[table][slot];
if (method == null)
Methods[table][slot] = method = MarshalUtil.GetDelegate<T>(Tables, table, slot);
return (T)method;
}
else
{
if (Specializations == null)
Specializations = new ConcurrentDictionary<(short, short, int), Delegate>();
var key = (specialiation, table, slot);
if (!Specializations.TryGetValue(key, out var method))
Specializations[key] = method = MarshalUtil.GetDelegate<T>(Tables, table, slot);
return (T)method;
}
}
public unsafe static IntPtr* CloneTable(List<SafeUnmanagedMemoryHandle> cache, IntPtr instance, int offset, int size)
{
var sizeInBytes = size * sizeof(IntPtr);
var src = ((*(IntPtr*)instance) + offset).ToPointer();
var entries = (IntPtr*)Marshal.AllocHGlobal(sizeInBytes);
Buffer.MemoryCopy(src, entries, sizeInBytes, sizeInBytes);
cache.Add(new SafeUnmanagedMemoryHandle((IntPtr)entries, true));
return entries;
}
}
}