Browse Source

Changed the native ctor to only patch the v-table entry of the virtual dtor, if any.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/256/merge
Dimitar Dobrev 10 years ago
parent
commit
2885200732
  1. 103
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  2. 9
      src/Generator/Options.cs

103
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -1254,6 +1254,7 @@ namespace CppSharp.Generators.CSharp @@ -1254,6 +1254,7 @@ namespace CppSharp.Generators.CSharp
}
WriteLine("private static void*[] __ManagedVTables;");
WriteLine("private static void*[] __ManagedVTablesDtorOnly;");
WriteLine("private static void*[] _Thunks;");
NewLine();
@ -1265,7 +1266,8 @@ namespace CppSharp.Generators.CSharp @@ -1265,7 +1266,8 @@ namespace CppSharp.Generators.CSharp
private void GenerateVTableClassSetup(Class @class, IList<VTableComponent> wrappedEntries)
{
WriteLine("void SetupVTables()");
const string destructorOnly = "destructorOnly";
WriteLine("private void SetupVTables(bool {0} = false)", destructorOnly);
WriteStartBraceIndent();
WriteLine("if (__OriginalVTables != null)");
@ -1278,6 +1280,13 @@ namespace CppSharp.Generators.CSharp @@ -1278,6 +1280,13 @@ namespace CppSharp.Generators.CSharp
NewLine();
var hasVirtualDtor = wrappedEntries.Any(e => e.Method.IsDestructor);
if (!hasVirtualDtor)
{
WriteLine("if ({0})", destructorOnly);
WriteLineIndent("return;");
}
// Get the _Thunks
WriteLine("if (_Thunks == null)");
WriteStartBraceIndent();
@ -1300,19 +1309,41 @@ namespace CppSharp.Generators.CSharp @@ -1300,19 +1309,41 @@ namespace CppSharp.Generators.CSharp
NewLine();
if (hasVirtualDtor)
{
WriteLine("if ({0})", destructorOnly);
WriteStartBraceIndent();
WriteLine("if (__ManagedVTablesDtorOnly == null)");
WriteStartBraceIndent();
AllocateNewVTables(@class, wrappedEntries, true);
WriteCloseBraceIndent();
WriteLine("else");
WriteStartBraceIndent();
}
WriteLine("if (__ManagedVTables == null)");
WriteStartBraceIndent();
if (Options.IsMicrosoftAbi)
AllocateNewVTablesMS(@class, wrappedEntries);
else
AllocateNewVTablesItanium(@class, wrappedEntries);
AllocateNewVTables(@class, wrappedEntries, false);
if (hasVirtualDtor)
WriteCloseBraceIndent();
WriteCloseBraceIndent();
NewLine();
}
private void SaveOriginalVTablePointers(ICollection<VFTableInfo> vfTables)
private void AllocateNewVTables(Class @class, IList<VTableComponent> wrappedEntries,
bool destructorOnly)
{
if (Options.IsMicrosoftAbi)
AllocateNewVTablesMS(@class, wrappedEntries, destructorOnly);
else
AllocateNewVTablesItanium(@class, wrappedEntries, destructorOnly);
}
private void SaveOriginalVTablePointers(IEnumerable<VFTableInfo> vfTables)
{
if (Driver.Options.IsMicrosoftAbi)
WriteLine("__OriginalVTables = new void*[] {{ {0} }};",
@ -1321,9 +1352,11 @@ namespace CppSharp.Generators.CSharp @@ -1321,9 +1352,11 @@ namespace CppSharp.Generators.CSharp
WriteLine("__OriginalVTables = new void*[] { native->vfptr0.ToPointer() };");
}
private void AllocateNewVTablesMS(Class @class, IList<VTableComponent> wrappedEntries)
private void AllocateNewVTablesMS(Class @class, IList<VTableComponent> wrappedEntries,
bool destructorOnly)
{
WriteLine("__ManagedVTables = new void*[{0}];", @class.Layout.VFTables.Count);
var managedVTables = destructorOnly ? "__ManagedVTablesDtorOnly" : "__ManagedVTables";
WriteLine("{0} = new void*[{1}];", managedVTables, @class.Layout.VFTables.Count);
for (int tableIndex = 0; tableIndex < @class.Layout.VFTables.Count; tableIndex++)
{
@ -1331,63 +1364,69 @@ namespace CppSharp.Generators.CSharp @@ -1331,63 +1364,69 @@ namespace CppSharp.Generators.CSharp
var size = vfptr.Layout.Components.Count;
WriteLine("var vfptr{0} = Marshal.AllocHGlobal({1} * {2});",
tableIndex, size, Driver.TargetInfo.PointerWidth / 8);
WriteLine("__ManagedVTables[{0}] = vfptr{0}.ToPointer();", tableIndex);
WriteLine("{0}[{1}] = vfptr{1}.ToPointer();", managedVTables, tableIndex);
AllocateNewVTableEntries(vfptr.Layout.Components, wrappedEntries, tableIndex);
AllocateNewVTableEntries(vfptr.Layout.Components, wrappedEntries, tableIndex,
destructorOnly);
}
WriteCloseBraceIndent();
NewLine();
for (var i = 0; i < @class.Layout.VFTables.Count; i++)
WriteLine("native->vfptr{0} = new IntPtr(__ManagedVTables[{0}]);", i);
WriteLine("native->vfptr{0} = new IntPtr({1}[{0}]);", i, managedVTables);
}
private void AllocateNewVTablesItanium(Class @class, IList<VTableComponent> wrappedEntries)
private void AllocateNewVTablesItanium(Class @class, IList<VTableComponent> wrappedEntries,
bool destructorOnly)
{
WriteLine("__ManagedVTables = new void*[1];");
var managedVTables = destructorOnly ? "__ManagedVTablesDtorOnly" : "__ManagedVTables";
WriteLine("{0} = new void*[1];", managedVTables);
var size = @class.Layout.Layout.Components.Count;
var pointerSize = Driver.TargetInfo.PointerWidth / 8;
WriteLine("var vtptr = Marshal.AllocHGlobal({0} * {1});", size, pointerSize);
WriteLine("var vfptr0 = vtptr + {0} * {1};", VTables.ItaniumOffsetToTopAndRTTI, pointerSize);
WriteLine("__ManagedVTables[0] = vfptr0.ToPointer();");
WriteLine("{0}[0] = vfptr0.ToPointer();", managedVTables);
AllocateNewVTableEntries(@class.Layout.Layout.Components,
wrappedEntries, tableIndex: 0);
wrappedEntries, 0, destructorOnly);
WriteCloseBraceIndent();
NewLine();
WriteLine("native->vfptr0 = new IntPtr(__ManagedVTables[0]);");
WriteLine("native->vfptr0 = new IntPtr({0}[0]);", managedVTables);
}
private void AllocateNewVTableEntries(IList<VTableComponent> entries,
IList<VTableComponent> wrappedEntries, int tableIndex)
IList<VTableComponent> wrappedEntries, int tableIndex, bool destructorOnly)
{
var pointerSize = Driver.TargetInfo.PointerWidth / 8;
for (int i = 0; i < entries.Count; i++)
for (var i = 0; i < entries.Count; i++)
{
var entry = entries[i];
var offsetInBytes = pointerSize
var offset = pointerSize
* (i - (Options.IsMicrosoftAbi ? 0 : VTables.ItaniumOffsetToTopAndRTTI));
var nativeVftableEntry = string.Format("*(void**)(native->vfptr{0} + {1})", tableIndex, offset);
var managedVftableEntry = string.Format("*(void**)(vfptr{0} + {1})", tableIndex, offset);
if ((entry.Kind == VTableComponentKind.FunctionPointer ||
entry.Kind == VTableComponentKind.DeletingDtorPointer) &&
!entry.IsIgnored())
WriteLine("*(void**)(vfptr{0} + {1}) = _Thunks[{2}];", tableIndex,
offsetInBytes, wrappedEntries.IndexOf(entry));
!entry.IsIgnored() &&
(!destructorOnly || entry.Method.IsDestructor ||
Driver.Options.ExplicitlyPatchedVirtualFunctions.Contains(entry.Method.OriginalName)))
WriteLine("{0} = _Thunks[{1}];", managedVftableEntry, wrappedEntries.IndexOf(entry));
else
WriteLine("*(void**)(vfptr{0} + {1}) = *(void**)(native->vfptr{0} + {1});",
tableIndex, offsetInBytes);
WriteLine("{0} = {1};", managedVftableEntry, nativeVftableEntry);
}
}
private void GenerateVTableClassSetupCall(Class @class)
private void GenerateVTableClassSetupCall(Class @class, bool destructorOnly = false)
{
if (@class.IsDynamic && GetUniqueVTableMethodEntries(@class).Count > 0)
WriteLine("SetupVTables();");
WriteLine("SetupVTables({0});", destructorOnly ? "true" : string.Empty);
}
private void GenerateVTableManagedCall(Method method)
@ -1891,7 +1930,7 @@ namespace CppSharp.Generators.CSharp @@ -1891,7 +1930,7 @@ namespace CppSharp.Generators.CSharp
PopIndent();
WriteLine("else");
PushIndent();
GenerateVTableClassSetupCall(@class);
GenerateVTableClassSetupCall(@class, destructorOnly: true);
PopIndent();
}
}
@ -2496,14 +2535,8 @@ namespace CppSharp.Generators.CSharp @@ -2496,14 +2535,8 @@ namespace CppSharp.Generators.CSharp
}
else
{
if (operatorParam != null)
{
names.Insert(instanceIndex, @params[0].Name);
}
else
{
names.Insert(instanceIndex, GetInstanceParam(function));
}
names.Insert(instanceIndex,
operatorParam != null ? @params[0].Name : GetInstanceParam(function));
}
}

9
src/Generator/Options.cs

@ -11,7 +11,7 @@ namespace CppSharp @@ -11,7 +11,7 @@ namespace CppSharp
{
public class DriverOptions : ParserOptions
{
static public bool IsUnixPlatform
public static bool IsUnixPlatform
{
get
{
@ -44,6 +44,8 @@ namespace CppSharp @@ -44,6 +44,8 @@ namespace CppSharp
CodeFiles = new List<string>();
StripLibPrefix = true;
ExplicitlyPatchedVirtualFunctions = new List<string>();
}
// General options
@ -186,6 +188,11 @@ namespace CppSharp @@ -186,6 +188,11 @@ namespace CppSharp
public bool GenerateDefaultValuesForArguments { get; set; }
public bool StripLibPrefix { get; set; }
/// <summary>
/// C# end only: force patching of the virtual entries of the functions in this list.
/// </summary>
public List<string> ExplicitlyPatchedVirtualFunctions { get; private set; }
}
public class InvalidOptionException : Exception

Loading…
Cancel
Save