private static NativeObject BuildDebuggableObject(XaeiOSObject xaeiosObject, VTable vtable, IntRef fieldCounter) { NativeObject debuggableObject = new NativeObject(); // add fields from base class // update field counter along the way so that we know which slots correspond to which field names if (vtable != GetSystemObjectVTable()) { debuggableObject[DebugBaseKey] = var.Cast<NativeObject>(BuildDebuggableObject( xaeiosObject, vtable.BaseVTable, fieldCounter )); } // retreive debug information for class through vtable VTableDebugInfo debugInfo = vtable.DebugInfo; // apply debug information to object instance { debuggableObject["FullName"] = var.Cast<string>(debugInfo.FullName); // fields NativeArray<string> fieldNames = debugInfo.Fields; for (int i = 0; i < fieldNames.Length; i++) { debuggableObject[fieldNames[i]] = xaeiosObject[fieldCounter.Value + i]; } fieldCounter.Value += fieldNames.Length; } return debuggableObject; }
internal static Array CreateArray(VTable elementTypeVTable, int length) { Class elementType = elementTypeVTable.Class; Class arrayType; if (_arrayTypeCache.ContainsKey(elementType)) { arrayType = _arrayTypeCache[elementType]; } else { VTable arrayVtable = (VTable)(typeof(Array).TypeHandle); arrayType = CreateClass( elementType.Namespace, elementType.Name, elementType.Assembly, arrayVtable.Class.VTableDataPointer, elementType, false, true); _arrayTypeCache[elementType] = arrayType; } XaeiOSObject array = var.Cast<NativeArray>(new NativeArray(length)).Cast<XaeiOSObject>(); array.VTable = arrayType.VTable; return var.Cast<XaeiOSObject>(array).Cast<Array>(); }
private static unsafe object TryCast(XaeiOSObject obj, VTable typeVTable) { return Cast(obj, typeVTable, false); }
private static bool ImplementsInterface(VTable vtable, VTable interfaceVtable) { // TODO: This may not cover all cases, what if an interface implements an interface? NativeObject interfaces = vtable.Interfaces; string[] keys = GetKeys(interfaces); for (int i = 0; i < keys.Length; i++) { if (GenerateCodeToDereferenceVTableDataPointer(keys[i]) == interfaceVtable) { return true; } } return false; }
private static unsafe object Cast(XaeiOSObject obj, VTable typeVtable, bool throwError) { if (obj == null) { if (throwError) { throw new InvalidCastException("Cannot cast null"); } else { return null; } } if (typeVtable == null) { throw new ExecutionEngineException("Cannot cast to null type"); } bool isInterface = (typeVtable.Flags & VTableFlags.IsInterface) != 0; VTable vtable = obj.VTable; if (vtable == null) { throw new ExecutionEngineException("Could not find vtable for object"); } while (vtable != null) { if (vtable == typeVtable) { return obj; } else if (isInterface && ImplementsInterface(vtable, typeVtable)) { return obj; } else { vtable = vtable.BaseVTable; } } if (throwError) { throw new InvalidCastException(string.NativeConcat(new string[] { "Cannot cast ", vtable.Class.FullName, " to type ", typeVtable.Class.FullName })); } else { return null; } }
private static extern XaeiOSObject GenerateCodeForNewObject(VTable vtable);