Skip to content

Commit f3533f9

Browse files
limokaKasuromi
andauthored
Small Il2CppInterop fixes (#94)
* Fix injected fields incorrectly being initialized on derived types * Fix exception on type with abstract method * Prevent delegate type names from containing assembly names * Fix setting null to Il2CppReferenceField value causing exception * Fix il2cpp detour not applying if target type is a blittable struct Co-authored-by: Kasuromi <29818914+Kasuromi@users.noreply.github.com>
1 parent 441577f commit f3533f9

4 files changed

Lines changed: 43 additions & 13 deletions

File tree

Il2CppInterop.HarmonySupport/HarmonyBackendComponent.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using HarmonyLib.Public.Patching;
22
using Il2CppInterop.Common.Host;
3-
using Il2CppInterop.Runtime.InteropTypes;
3+
using Il2CppInterop.Runtime;
4+
using Il2CppInterop.Runtime.Injection;
45

56
namespace Il2CppInterop.HarmonySupport;
67

@@ -21,7 +22,10 @@ internal class HarmonySupportComponent : IHostComponent
2122

2223
private static void TryResolve(object sender, PatchManager.PatcherResolverEventArgs args)
2324
{
24-
if (args.Original.DeclaringType?.IsSubclassOf(typeof(Il2CppObjectBase)) != true)
25+
var declaringType = args.Original.DeclaringType;
26+
if (declaringType == null) return;
27+
if (Il2CppType.From(declaringType, false) == null ||
28+
ClassInjector.IsManagedTypeInjected(declaringType))
2529
{
2630
return;
2731
}

Il2CppInterop.Runtime/DelegateSupport.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ internal static Type GetOrCreateDelegateType(MethodSignature signature, MethodIn
3737

3838
private static Type CreateDelegateType(MethodInfo managedMethodInner, MethodSignature signature)
3939
{
40-
var newType = ModuleBuilder.DefineType(
41-
"Il2CppToManagedDelegate_" + managedMethodInner.DeclaringType.FullName + "_" + signature.GetHashCode() + (signature.HasThis ? "HasThis" : "") +
42-
(signature.ConstructedFromNative ? "FromNative" : ""), TypeAttributes.Sealed | TypeAttributes.Public,
40+
var typeName = "Il2CppToManagedDelegate_" + managedMethodInner.DeclaringType + "_" + signature.GetHashCode() +
41+
(signature.HasThis ? "HasThis" : "") +
42+
(signature.ConstructedFromNative ? "FromNative" : "");
43+
44+
var newType = ModuleBuilder.DefineType(typeName, TypeAttributes.Sealed | TypeAttributes.Public,
4345
typeof(MulticastDelegate));
4446
newType.SetCustomAttribute(new CustomAttributeBuilder(
4547
typeof(UnmanagedFunctionPointerAttribute).GetConstructor(new[] { typeof(CallingConvention) })!,

Il2CppInterop.Runtime/Injection/ClassInjector.cs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ public static bool IsTypeRegisteredInIl2Cpp(Type type)
128128
var currentPointer = Il2CppClassPointerStore.GetNativeClassPointer(type);
129129
if (currentPointer != IntPtr.Zero)
130130
return true;
131+
if (IsManagedTypeInjected(type)) return true;
132+
133+
return false;
134+
}
135+
136+
internal static bool IsManagedTypeInjected(Type type)
137+
{
131138
lock (InjectedTypes)
132139
{
133140
if (InjectedTypes.Contains(type.FullName))
@@ -305,7 +312,12 @@ public static void RegisterTypeInIl2Cpp(Type type, RegisterTypeOptions options)
305312

306313
methodPointerArray[0] = ConvertStaticMethod(FinalizeDelegate, "Finalize", classPointer);
307314
var finalizeMethod = UnityVersionHandler.Wrap(methodPointerArray[0]);
308-
if (!type.IsAbstract) methodPointerArray[1] = ConvertStaticMethod(CreateEmptyCtor(type, fieldsToInject), ".ctor", classPointer);
315+
var fieldsToInitialize = type
316+
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
317+
.Where(IsFieldEligible)
318+
.ToArray();
319+
320+
if (!type.IsAbstract) methodPointerArray[1] = ConvertStaticMethod(CreateEmptyCtor(type, fieldsToInitialize), ".ctor", classPointer);
309321
var infos = new Dictionary<(string, int, bool), int>(eligibleMethods.Length);
310322
for (var i = 0; i < eligibleMethods.Length; i++)
311323
{
@@ -372,6 +384,18 @@ static void FindAbstractMethods(List<INativeMethodInfoStruct> list, INativeClass
372384
}
373385

374386
var abstractV = 0;
387+
388+
INativeMethodInfoStruct HandleAbstractMethod(int position)
389+
{
390+
if (!extendsAbstract) throw new NullReferenceException("VTable method was null even though base type isn't abstract");
391+
392+
var nativeMethodInfoStruct = abstractBaseMethods[abstractV++];
393+
394+
vTablePointer[position].method = nativeMethodInfoStruct.MethodInfoPointer;
395+
vTablePointer[position].methodPtr = nativeMethodInfoStruct.MethodPointer;
396+
return nativeMethodInfoStruct;
397+
}
398+
375399
for (var i = 0; i < baseClassPointer.VtableCount; i++)
376400
{
377401
vTablePointer[i] = baseVTablePointer[i];
@@ -380,18 +404,18 @@ static void FindAbstractMethods(List<INativeMethodInfoStruct> list, INativeClass
380404

381405
if (baseVTablePointer[i].method == default)
382406
{
383-
if (!extendsAbstract) throw new NullReferenceException("VTable method was null even though base type isn't abstract");
384-
385-
baseMethod = abstractBaseMethods[abstractV++];
386-
387-
vTablePointer[i].method = baseMethod.MethodInfoPointer;
388-
vTablePointer[i].methodPtr = baseMethod.MethodPointer;
407+
baseMethod = HandleAbstractMethod(i);
389408
}
390409
else
391410
{
392411
baseMethod = UnityVersionHandler.Wrap(vTablePointer[i].method);
393412
}
394413

414+
if (baseMethod.Name == IntPtr.Zero)
415+
{
416+
baseMethod = HandleAbstractMethod(i);
417+
}
418+
395419
var methodName = Marshal.PtrToStringAnsi(baseMethod.Name);
396420

397421
if (methodName == "Finalize") // slot number is not static

Il2CppInterop.Runtime/InteropTypes/Fields/Il2CppReferenceField.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public TRefObj Value
2828

2929
public void Set(TRefObj value)
3030
{
31-
*GetPointerToData() = value.Pointer;
31+
*GetPointerToData() = value != null ? value.Pointer : IntPtr.Zero;
3232
}
3333

3434
public static implicit operator TRefObj(Il2CppReferenceField<TRefObj> _this)

0 commit comments

Comments
 (0)