C# / P/Invoke 基礎

1 概要

C# (シーシャープ) は .NET 環境で動作するオブジェクト指向言語です。型安全で例外処理が充実しており、Java に似た構文を持ちます。P/Invoke (Platform Invocation Services) は .NET アプリケーションから C/C++ などで書かれたネイティブコード (DLL) を呼び出す仕組みです。

このリポジトリの prod/calc.net/ は C ライブラリ(libcalc)を .NET から利用するための実装例です。prod/calc.net/libsrc/CalcLib/Internal/NativeMethods.cs[DllImport] 属性を使った P/Invoke 定義を行い、CalcLibrary.cs がこれをラップして .NET らしいインターフェース (例外・型安全・CalcResult クラス) を提供します。CalcApp がこのライブラリを使うサンプルアプリです。

C 言語開発者が .NET 連携を理解するには、C# の基礎に加えて P/Invoke の仕組みを習得することが重要です。

2 習得目標

3 学習マテリアル

3.1 公式ドキュメント

4 このリポジトリとの関連

4.1 使用箇所 (具体的なファイル・コマンド)

P/Invoke 定義 (prod/calc.net/libsrc/CalcLib/Internal/NativeMethods.cs) の概要:

using System.Runtime.InteropServices;

namespace CalcLib.Internal;

internal static class NativeMethods
{
    // C 関数: int calcHandler(int kind, int a, int b, int *result)
    [DllImport("libcalc", CallingConvention = CallingConvention.Cdecl)]
    internal static extern int calcHandler(int kind, int a, int b, out int result);
}

C# ラッパー (prod/calc.net/libsrc/CalcLib/CalcLibrary.cs) の概要:

namespace CalcLib;

public class CalcLibrary
{
    public CalcResult Calculate(CalcKind kind, int a, int b)
    {
        int nativeResult;
        int status = Internal.NativeMethods.calcHandler((int)kind, a, b, out nativeResult);

        if (status != 0)
        {
            throw new CalcException($"計算エラー: status={status}");
        }

        return new CalcResult(nativeResult);
    }
}

ネイティブライブラリのロード設定 (prod/calc.net/src/CalcApp/ModuleInitializer.cs):

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace CalcApp;

internal static class ModuleInitializer
{
    [ModuleInitializer]
    internal static void Initialize()
    {
        // libcalc の検索パスを設定
        NativeLibrary.SetDllImportResolver(
            typeof(CalcLib.CalcLibrary).Assembly,
            DllImportResolver);
    }
    // ...
}

CalcLib のファイル構成:

prod/calc.net/libsrc/CalcLib/
+-- CalcLibrary.cs          # メインライブラリクラス
+-- CalcKind.cs             # 計算種別の列挙型
+-- CalcResult.cs           # 計算結果クラス
+-- CalcException.cs        # カスタム例外クラス
+-- Internal/
    +-- NativeMethods.cs    # P/Invoke 定義

4.2 関連ドキュメント