Files
BQP/srcs/RobotNet10/RobotApp/Communication/CeresSharp/Native/NativeHelpers.cs
2026-07-13 09:25:40 +07:00

85 lines
3.1 KiB
C#

using System;
using System.Text;
using CeresSharp.Exceptions;
namespace CeresSharp.Native;
/// <summary>
/// Helper class for native interop operations.
/// Provides utilities for error handling, StringBuilder management, and common patterns.
/// </summary>
internal static class NativeHelpers
{
private const int DefaultErrorMessageCapacity = 256;
// Thread-local buffer pool to avoid allocating a new StringBuilder every call
[ThreadStatic]
private static StringBuilder? t_errorMessageBuffer;
/// <summary>
/// Gets a reusable StringBuilder for error messages.
/// Uses thread-local storage to avoid allocation on each native call.
/// </summary>
internal static StringBuilder CreateErrorMessageBuffer(int capacity = DefaultErrorMessageCapacity)
{
var sb = t_errorMessageBuffer;
if (sb != null && sb.Capacity >= capacity)
{
sb.Clear();
return sb;
}
sb = new StringBuilder(capacity);
t_errorMessageBuffer = sb;
return sb;
}
/// <summary>
/// Extracts error message from StringBuilder, returning null if empty.
/// </summary>
internal static string? ExtractErrorMessage(StringBuilder sb)
{
return sb.Length > 0 ? sb.ToString() : null;
}
/// <summary>
/// Checks error code and throws exception if not successful.
/// </summary>
/// <param name="errorCode">The error code to check.</param>
/// <param name="errorMessage">Optional error message. If null, will be retrieved from native code.</param>
/// <exception cref="CeresException">Thrown when error code is not Success.</exception>
internal static void CheckError(CeresErrorCode errorCode, string? errorMessage = null)
{
if (errorCode != CeresErrorCode.Success)
{
if (errorMessage == null)
{
var errorMessagePtr = CeresNative.ceres_wrapper_get_error_message(errorCode);
errorMessage = errorMessagePtr != IntPtr.Zero
? System.Runtime.InteropServices.Marshal.PtrToStringAnsi(errorMessagePtr)
: $"Unknown error code: {errorCode}";
}
throw new CeresException(errorCode, errorMessage);
}
}
/// <summary>
/// Executes a native operation with error handling.
/// </summary>
/// <param name="operation">The operation that returns an error code.</param>
/// <param name="errorMessageBuffer">Optional StringBuilder for error messages.</param>
/// <exception cref="CeresException">Thrown when the operation fails.</exception>
internal static void ExecuteWithErrorHandling(
Func<StringBuilder, CeresErrorCode> operation,
StringBuilder? errorMessageBuffer = null)
{
errorMessageBuffer ??= CreateErrorMessageBuffer();
var errorCode = operation(errorMessageBuffer);
if (errorCode != CeresErrorCode.Success)
{
var errorMessage = ExtractErrorMessage(errorMessageBuffer);
throw new CeresException(errorCode, errorMessage);
}
}
}