using System; using System.Runtime.InteropServices; using CeresSharp.Native; namespace CeresSharp.Native.SafeHandles; /// /// Safe handle for Ceres Problem. /// Note: Uses official C API (ceres_create_problem/ceres_free_problem). /// internal sealed class ProblemHandle : BaseSafeHandle { private ProblemHandle() : base() { } private ProblemHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) { } public static ProblemHandle Create() { // Note: ceres_create_problem is from official C API, not wrapper // We'll need to import it separately or use wrapper function if available var handle = CeresNative.ceres_create_problem(); if (handle == IntPtr.Zero) { throw new Exceptions.CeresException(Exceptions.CeresErrorCode.OutOfMemory, "Failed to create problem"); } return new ProblemHandle(handle, true); } public static ProblemHandle CreateWithOptions(IntPtr problemOptions) { var handle = CeresNative.ceres_wrapper_create_problem_with_options(problemOptions); if (handle == IntPtr.Zero) { throw new Exceptions.CeresException(Exceptions.CeresErrorCode.OutOfMemory, "Failed to create problem with options"); } return new ProblemHandle(handle, true); } protected override void ReleaseNativeHandle(IntPtr handle) { // Note: ceres_free_problem is from official C API // Add null check to prevent crash if handle is invalid if (handle != IntPtr.Zero) { try { CeresNative.ceres_free_problem(handle); } catch { // Ignore errors - handle may already be freed or invalid // This can happen in finalizer thread } } } }