using System;
using System.Runtime.InteropServices;
using Unity.Jobs;
namespace UnityEngine.XR.ARKit
{
///
/// An interface for Objective-C objects that derive from NSObject.
///
interface INSObject
{
///
/// Gets the underlying Objective-C pointer.
///
/// Returns the underlying Objective-C pointer.
IntPtr AsIntPtr();
///
/// Sets the underlying native pointer for the object.
///
///
/// Warning: This allows you to change this object into any arbitrary object, even one of a different type.
/// Incorrect usage is undefined behavior and can cause your application to crash.
///
/// The pointer to which the object's underlying pointer will be set.
void SetUnderlyingNativePtr(IntPtr ptr);
///
/// The of the type of this .
///
Class staticClass { get; }
}
///
/// Utility methods for interacting with [NSObjects](https://developer.apple.com/documentation/objectivec/nsobject?language=objc).
///
static class NSObject
{
///
/// May be used by constructors to specify the type of object initialization.
///
public enum Initialization
{
///
/// Use for default constructors, since structs cannot have parameterless constructors.
///
Default
}
public static string ToString(T instance) where T : struct, INSObject
{
using (var description = GetDescription(instance.AsIntPtr()))
{
return description.ToString();
}
}
public static bool ArePointersEqual(T? lhs, T? rhs) where T : struct, INSObject
{
// Both have a value, so compare values
if (lhs.HasValue && rhs.HasValue)
return lhs.Value.AsIntPtr() == rhs.Value.AsIntPtr();
// lhs has a value; rhs is null
if (lhs.HasValue)
return lhs.Value.AsIntPtr() == IntPtr.Zero;
// rhs has a value; lhs is null
if (rhs.HasValue)
return rhs.Value.AsIntPtr() == IntPtr.Zero;
// Neither has a value
return true;
}
public static bool IsEqual(T lhs, U rhs)
where T : struct, INSObject
where U : struct, INSObject
=> IsEqual(lhs.AsIntPtr(), rhs.AsIntPtr());
public static int GetHashCode(T instance) where T : struct, INSObject =>
GetHash(instance.AsIntPtr()).GetHashCode();
public static int GetRetainCount(T obj) where T : struct, INSObject => CFGetRetainCount(obj.AsIntPtr());
public static void Release(IntPtr ptr)
{
if (ptr != IntPtr.Zero)
{
CFRelease(ptr);
}
}
public static void Dispose(ref IntPtr ptr)
{
Release(ptr);
ptr = IntPtr.Zero;
}
struct ReleaseJob : IJob
{
public IntPtr ptr;
void IJob.Execute()
{
if (ptr != IntPtr.Zero)
{
CFRelease(ptr);
}
}
}
public static JobHandle Dispose(IntPtr ptr, JobHandle inputDependencies) => new ReleaseJob
{
ptr = ptr
}.Schedule(inputDependencies);
public static void Retain(IntPtr ptr)
{
if (ptr != IntPtr.Zero)
{
CFRetain(ptr);
}
}
public static void Retain(T obj) where T : struct, INSObject => Retain(obj.AsIntPtr());
#if UNITY_EDITOR || !UNITY_XR_ARKIT_LOADER_ENABLED
static void CFRetain(IntPtr obj) { }
static void CFRelease(IntPtr obj) { }
static int CFGetRetainCount(IntPtr obj) => default;
static NSString GetDescription(IntPtr self) => default;
static bool IsEqual(IntPtr self, IntPtr other) => default;
static ulong GetHash(IntPtr self) => default;
#else
[DllImport("__Internal")]
static extern void CFRetain(IntPtr obj);
[DllImport("__Internal")]
static extern void CFRelease(IntPtr obj);
[DllImport("__Internal")]
static extern int CFGetRetainCount(IntPtr obj);
[DllImport("__Internal", EntryPoint = "NSObject_get_description")]
static extern NSString GetDescription(IntPtr self);
[DllImport("__Internal", EntryPoint = "NSObject_isEqual_")]
static extern bool IsEqual(IntPtr self, IntPtr other);
[DllImport("__Internal", EntryPoint = "NSObject_get_hash")]
static extern ulong GetHash(IntPtr self);
#endif
}
}