NativeSdk 패키지: unsafe, P/Invoke, Native AOT 관련 설정이 미리 입혀진 SDK 패키지

Native AOT는 정확한 설정 방법과 활용 방법을 안다면 어렵지 않게 시작할 수 있습니다. 하지만, 사전에 AOT 사용을 위해서 준비해야 하는 세레모니가 많고 복잡하기에 SDK 스타일 패키지로 이를 간소화할 수 있다면 좋겠다고 생각해서 리서치해보고 nuget으로 패키징해본 것을 공유합니다.

.NET 8 이상부터 사용 가능하며, .NET 10에서 File-based App과 함께 쓰시면 더욱 좋습니다. 예를 들어, 아래와 같이 코드를 작성한 후 복잡한 명령어를 주지 않고, dotnet publish app.cs 로 실행하기만 하면 곧바로 Native AOT가 입혀진 네이티브 실행 파일이 만들어지게 됩니다. 이 때, 기본 SDK로 Microsoft.NET.Sdk 를 상속받게 되어있으니 .NET 8, 9, 10 혹은 그 이후 버전을 사용하더라도 자동으로 새 버전을 따라가도록 설계되어 있습니다.

#:sdk NativeSdk@0.5.1

unsafe
{
    const int ArraySize = 10;

    // stackalloc으로 스택에 메모리 할당
    int* arr = stackalloc int[ArraySize];

    // 랜덤 값으로 배열 초기화
    Random rand = new(42);
    Console.WriteLine("Before Sort:");
    for (int i = 0; i < ArraySize; i++)
    {
        arr[i] = rand.Next(1, 100);
        Console.Write($"{arr[i]} ");
    }
    Console.WriteLine();

    // QuickSort 실행
    QuickSort(arr, 0, ArraySize - 1);

    // 정렬 결과 출력
    Console.WriteLine("\nAfter Sort:");
    for (int i = 0; i < ArraySize; i++)
    {
        Console.Write($"{arr[i]} ");
    }
    Console.WriteLine();

    static void QuickSort(int* arr, int left, int right)
    {
        if (left >= right) return;

        int pivotIndex = Partition(arr, left, right);
        QuickSort(arr, left, pivotIndex - 1);
        QuickSort(arr, pivotIndex + 1, right);
    }

    static int Partition(int* arr, int left, int right)
    {
        int pivot = arr[right];
        int i = left - 1;

        for (int j = left; j < right; j++)
        {
            if (arr[j] <= pivot)
            {
                i++;
                (arr[i], arr[j]) = (arr[j], arr[i]);  // 튜플 스왑
            }
        }

        (arr[i + 1], arr[right]) = (arr[right], arr[i + 1]);
        return i + 1;
    }
}

다만 약간 아쉬운 것은, unsafe 키워드를 MSBuild 프로퍼티 레벨에서 전역적으로 지정하는 기능은 아직 제공되지 않고 있는 것이 아쉽습니다. 추후 닷넷 11이나 이후 버전에서 관련된 기능이 들어간다면, File-based App 포맷을 유지하면서도 곧바로 포인터를 쓸 수 있는 네이티브 프로그래밍이나 C 언어용 DLL Export 코드를 더 간결하게 만들 수도 있을 것입니다.

2개의 좋아요