-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHelpers.cs
More file actions
91 lines (84 loc) · 5.45 KB
/
Copy pathHelpers.cs
File metadata and controls
91 lines (84 loc) · 5.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[module: SkipLocalsInit] // Same semantics as C for inlined functions
namespace Box3D
{
internal static class Box3DModuleInitializer
{
[ModuleInitializer]
[SuppressMessage("Usage", "CA2255", Justification = "The native resolver must be registered before any Box3D P/Invoke is resolved.")]
internal static void InitializeNativeLibraryResolver()
{
// Register before the Box3D type initializer performs its first P/Invoke.
// Registering from that type initializer is too late on Apple AOT runtimes,
// which resolve the import triggered by b3SetAssertFcn before entering the initializer body.
NativeLibrary.SetDllImportResolver(typeof(Box3D).Assembly, (libraryName, assembly, searchPath) =>
{
bool useDebug = AppContext.TryGetSwitch("Box3D.Debug", out bool debug) && debug; // Set in Box3D.targets
string suffix = useDebug ? "d" : "";
// Apple frameworks fail to be searched by default - see see https://github.com/dotnet/macios/issues/21238
if (OperatingSystem.IsIOS() || OperatingSystem.IsTvOS() || OperatingSystem.IsMacCatalyst())
return NativeLibrary.Load($"@rpath/box3d{suffix}.framework/box3d{suffix}");
return NativeLibrary.Load($"box3d{suffix}", assembly, searchPath);
});
}
}
unsafe partial class Box3D
{
static Box3D()
{
// Route native B3_ASSERT to C# Trace.Assert so asserts are visible
// through the .NET debug/trace infrastructure without crashing the process.
// This crash occurs through:
// - On MSVC: __debugbreak() — raises EXCEPTION_BREAKPOINT (Win32 exception, crash unless a debugger is attached)
// - On GCC/Clang: __builtin_trap() — raises SIGTRAP or SIGILL, immediate process termination
// In Release native binaries B3_ASSERT is stripped so this callback is never invoked — no overhead.
b3SetAssertFcn(&AssertCallback);
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static int AssertCallback(sbyte* condition, sbyte* fileName, int lineNumber)
{
string condStr = Marshal.PtrToStringUTF8((nint)condition) ?? "(null)";
string fileStr = Marshal.PtrToStringUTF8((nint)fileName) ?? "(null)";
Console.Error.WriteLine($"Box3D assertion failed: {condStr} at {fileStr}:{lineNumber}");
if (Debugger.IsAttached) Debugger.Break();
return 0; // suppress native __debugbreak()/__builtin_trap()
}
private static float nextafterf(float x, float y) // polyfill for the C function
{
return y < x ? MathF.BitDecrement(x) : MathF.BitIncrement(x);
}
/// <summary>Macro to determine if any id is null.</summary>
public static bool B3_IS_NULL(b3WorldId id) => id.index1 == 0;
/// <summary>Macro to determine if any id is null.</summary>
public static bool B3_IS_NULL(b3BodyId id) => id.index1 == 0;
/// <summary>Macro to determine if any id is null.</summary>
public static bool B3_IS_NULL(b3ShapeId id) => id.index1 == 0;
/// <summary>Macro to determine if any id is null.</summary>
public static bool B3_IS_NULL(b3JointId id) => id.index1 == 0;
/// <summary>Macro to determine if any id is null.</summary>
public static bool B3_IS_NULL(b3ContactId id) => id.index1 == 0;
/// <summary>Macro to determine if any id is non-null.</summary>
public static bool B3_IS_NON_NULL(b3WorldId id) => id.index1 != 0;
/// <summary>Macro to determine if any id is non-null.</summary>
public static bool B3_IS_NON_NULL(b3BodyId id) => id.index1 != 0;
/// <summary>Macro to determine if any id is non-null.</summary>
public static bool B3_IS_NON_NULL(b3ShapeId id) => id.index1 != 0;
/// <summary>Macro to determine if any id is non-null.</summary>
public static bool B3_IS_NON_NULL(b3JointId id) => id.index1 != 0;
/// <summary>Macro to determine if any id is non-null.</summary>
public static bool B3_IS_NON_NULL(b3ContactId id) => id.index1 != 0;
/// <summary>Compare two ids for equality. Doesn't work for b3WorldId. Don't mix types.</summary>
public static bool B3_ID_EQUALS(b3BodyId id1, b3BodyId id2) => id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.generation == id2.generation;
/// <summary>Compare two ids for equality. Doesn't work for b3WorldId. Don't mix types.</summary>
public static bool B3_ID_EQUALS(b3ShapeId id1, b3ShapeId id2) => id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.generation == id2.generation;
/// <summary>Compare two ids for equality. Doesn't work for b3WorldId. Don't mix types.</summary>
public static bool B3_ID_EQUALS(b3JointId id1, b3JointId id2) => id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.generation == id2.generation;
/// <summary>Compare two ids for equality. Doesn't work for b3WorldId. Don't mix types.</summary>
public static bool B3_ID_EQUALS(b3ContactId id1, b3ContactId id2) => id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.generation == id2.generation;
}
}