Fix native scripting interface method override in managed scripts on Clang-platforms
This commit is contained in:
@@ -1500,7 +1500,10 @@ namespace Flax.Build.Bindings
|
||||
var langInfo = ScriptingLangInfos[i];
|
||||
if (!langInfo.Enabled)
|
||||
continue;
|
||||
contents.AppendLine(count == 0 ? " if (wrapperIndex == 0)" : $" else if (wrapperIndex == {count})");
|
||||
if (count == 0)
|
||||
contents.AppendLine(" if (wrapperIndex == 0)");
|
||||
else
|
||||
contents.AppendLine($" else if (wrapperIndex == {count})");
|
||||
contents.AppendLine(" {");
|
||||
contents.AppendLine($" auto thunkPtr = &{classInfo.NativeName}Internal::{functionInfo.UniqueName}{langInfo.VirtualWrapperMethodsPostfix};");
|
||||
contents.AppendLine(" vtable[vtableIndex] = *(void**)&thunkPtr;");
|
||||
@@ -1516,6 +1519,50 @@ namespace Flax.Build.Bindings
|
||||
|
||||
scriptVTableIndex++;
|
||||
}
|
||||
|
||||
// Native interfaces override in managed code requires vtables hacking which requires additional inject on Clang-platforms
|
||||
if (buildData.Toolchain.Compiler == TargetCompiler.Clang && classInfo.IsClass && classInfo.Interfaces != null)
|
||||
{
|
||||
// Override vtable entries of interface methods (for each virtual function in each interface)
|
||||
foreach (var interfaceInfo in classInfo.Interfaces)
|
||||
{
|
||||
if (interfaceInfo.Access == AccessLevel.Private)
|
||||
continue;
|
||||
foreach (var functionInfo in interfaceInfo.Functions)
|
||||
{
|
||||
if (!functionInfo.IsVirtual)
|
||||
continue;
|
||||
contents.AppendLine(" {");
|
||||
{
|
||||
var thunkParams = string.Empty;
|
||||
var separator = false;
|
||||
for (var i = 0; i < functionInfo.Parameters.Count; i++)
|
||||
{
|
||||
var parameterInfo = functionInfo.Parameters[i];
|
||||
if (separator)
|
||||
thunkParams += ", ";
|
||||
separator = true;
|
||||
thunkParams += parameterInfo.Type;
|
||||
}
|
||||
var t = functionInfo.IsConst ? " const" : string.Empty;
|
||||
contents.AppendLine($" typedef {functionInfo.ReturnType} ({classInfo.NativeName}::*{functionInfo.UniqueName}_Signature)({thunkParams}){t};");
|
||||
}
|
||||
contents.AppendLine($" {functionInfo.UniqueName}_Signature funcPtr = &{classInfo.NativeName}::{functionInfo.Name};");
|
||||
contents.AppendLine(" const int32 vtableIndex = GetVTableIndex(vtable, entriesCount, *(void**)&funcPtr);");
|
||||
contents.AppendLine(" if (vtableIndex >= 0 && vtableIndex < entriesCount)");
|
||||
contents.AppendLine(" {");
|
||||
contents.AppendLine($" extern void {interfaceInfo.NativeName}Internal_{functionInfo.UniqueName}_VTableOverride(void*& vtableEntry, int32 wrapperIndex);");
|
||||
contents.AppendLine($" {interfaceInfo.NativeName}Internal_{functionInfo.UniqueName}_VTableOverride(vtable[vtableIndex], wrapperIndex);");
|
||||
contents.AppendLine(" }");
|
||||
contents.AppendLine(" else");
|
||||
contents.AppendLine(" {");
|
||||
contents.AppendLine($" LOG(Error, \"Failed to find the vtable entry for method {{0}} in class {{1}}\", TEXT(\"{functionInfo.Name}\"), TEXT(\"{classInfo.Name}\"));");
|
||||
contents.AppendLine(" }");
|
||||
contents.AppendLine(" }");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contents.AppendLine(" }");
|
||||
contents.AppendLine("");
|
||||
|
||||
@@ -2318,6 +2365,36 @@ namespace Flax.Build.Bindings
|
||||
contents.Append('}').Append(';').AppendLine();
|
||||
contents.AppendLine();
|
||||
|
||||
// Native interfaces override in managed code requires vtables hacking which requires additional inject on Clang-platforms
|
||||
if (buildData.Toolchain.Compiler == TargetCompiler.Clang)
|
||||
{
|
||||
// Generate functions that inject script wrappers into vtable entry
|
||||
foreach (var functionInfo in interfaceInfo.Functions)
|
||||
{
|
||||
if (!functionInfo.IsVirtual)
|
||||
continue;
|
||||
contents.AppendLine($"void {interfaceInfo.NativeName}Internal_{functionInfo.UniqueName}_VTableOverride(void*& vtableEntry, int32 wrapperIndex)");
|
||||
contents.AppendLine("{");
|
||||
for (int i = 0, count = 0; i < ScriptingLangInfos.Count; i++)
|
||||
{
|
||||
var langInfo = ScriptingLangInfos[i];
|
||||
if (!langInfo.Enabled)
|
||||
continue;
|
||||
if (count == 0)
|
||||
contents.AppendLine(" if (wrapperIndex == 0)");
|
||||
else
|
||||
contents.AppendLine($" else if (wrapperIndex == {count})");
|
||||
contents.AppendLine(" {");
|
||||
contents.AppendLine($" auto thunkPtr = &{interfaceInfo.NativeName}Internal::{functionInfo.UniqueName}{langInfo.VirtualWrapperMethodsPostfix};");
|
||||
contents.AppendLine(" vtableEntry = *(void**)&thunkPtr;");
|
||||
contents.AppendLine(" }");
|
||||
count++;
|
||||
}
|
||||
contents.AppendLine("}");
|
||||
contents.AppendLine("");
|
||||
}
|
||||
}
|
||||
|
||||
// Type initializer
|
||||
contents.Append($"ScriptingTypeInitializer {interfaceTypeNameNative}::TypeInitializer((BinaryModule*)GetBinaryModule{moduleInfo.Name}(), ");
|
||||
contents.Append($"StringAnsiView(\"{interfaceTypeNameManaged}\", {interfaceTypeNameManaged.Length}), &{interfaceTypeNameInternal}Internal::InitRuntime,");
|
||||
|
||||
Reference in New Issue
Block a user