# 通知設計書 6-Delegation.InitDelegate

## 概要

本ドキュメントは、VBCorLibライブラリにおけるDelegation.InitDelegateコールバック通知機構の設計を定義する。InitDelegate関数は既存のDelegate構造体を初期化し、関数ポインタを設定する軽量なデリゲート初期化方式を提供する。

### 本通知の処理概要

Delegation.InitDelegateは、Delegate型構造体（UDT）を直接初期化し、軽量COMオブジェクトとして使用可能にする通知機構である。NewDelegateとは異なり、動的メモリ確保を行わず、呼び出し元が保持する構造体をそのままデリゲートとして使用する。

**業務上の目的・背景**：NewDelegateはCoTaskMemAllocで動的メモリを確保するため、長時間稼働するオブジェクト（Ticker等）ではメモリリークやアプリケーション終了時のクラッシュのリスクがある。InitDelegateは呼び出し元が管理する構造体を使用するため、メモリ管理が明確で、オブジェクトのライフサイクルを制御しやすい。特にクラスのメンバとしてデリゲートを保持する場合に適している。

**通知の送信タイミング**：InitDelegateで初期化されたデリゲートオブジェクトに対してInvokeメソッドが呼び出された時点で、登録された関数が実行される。

**通知の受信者**：InitDelegate関数のpfn引数（AddressOfで指定）で登録された関数。

**通知内容の概要**：NewDelegateと同様、デリゲートの型に応じた引数が関数に渡される。

**期待されるアクション**：登録された関数が引数を受け取り、必要な処理を実行する。

## 通知種別

コールバック通知（構造体ベースの関数委譲）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Invoke呼び出し時に即時実行） |
| 優先度 | 呼び出し元の処理優先度に依存 |
| リトライ | 無 |

### 送信先決定ロジック

1. 呼び出し元でDelegate型構造体を宣言
2. InitDelegate(Struct, pfn)で構造体を初期化
3. 戻り値をデリゲート型として使用
4. デリゲート.Invoke(args...)で関数呼び出し

## 通知テンプレート

### InitDelegate関数シグネチャ

| 項目 | 内容 |
|-----|------|
| 関数名 | InitDelegate |
| 引数1 | ByRef Struct As Delegate（初期化対象構造体） |
| 引数2 | Optional ByVal pfn As Long（関数ポインタ） |
| 戻り値 | IUnknown（構造体へのオブジェクト参照） |

### 使用例（Tickerクラス内）

```vb
' クラスモジュール内
Private mDelegate As Delegate
Private mCallback As Action_T_T

Friend Sub Init(ByVal AddressOfCallback As Long)
    If AddressOfCallback <> vbNullPtr Then
        ' 構造体ベースのデリゲート初期化
        Set mCallback = InitDelegate(mDelegate, AddressOfCallback)
    End If
End Sub

Private Sub Class_Terminate()
    ' ObjectPtrで参照解除（Releaseを呼ばない）
    ObjectPtr(mCallback) = vbNullPtr
End Sub
```

### NewDelegateとInitDelegateの違い

| 項目 | NewDelegate | InitDelegate |
|-----|-------------|--------------|
| メモリ確保 | CoTaskMemAlloc | なし（呼び出し元構造体使用） |
| 参照カウント | あり（cRefs） | なし |
| Release処理 | CoTaskMemFree | 何もしない |
| 用途 | 一般的なデリゲート | 長寿命オブジェクトでのデリゲート |

### 添付ファイル

該当なし（プログラム内部機能）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Struct | Delegate型構造体 | 呼び出し元で宣言 | Yes |
| pfn | 関数ポインタ | AddressOf演算子 | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| メソッド呼び出し | delegate.Invoke() | Struct.pfn <> 0 | デリゲートのInvokeメソッド呼び出し |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| pfn未指定かつStruct.pfn = 0 | 関数ポインタが設定されていない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[InitDelegate Struct, pfn 呼び出し] --> B[Init でVTable初期化]
    B --> C[Struct.pfn = pfn]
    C --> D[Struct.pVTable = mOkVTablePtr]
    D --> E[ObjectPtr VarPtr Struct 返却]
    E --> F[呼び出し側で型キャスト]
    F --> G[delegate.Invoke args 呼び出し]
    G --> H[DelegationCode 経由で関数実行]
    H --> I[登録関数実行]
    I --> J[戻り値を返却]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（メモリ内処理のみ）

### 更新テーブル一覧

該当なし（メモリ内処理のみ）

#### 内部データ構造

| 構造体/変数 | 用途 |
|------------|------|
| Delegate | デリゲート構造体（pVTable, pfn） |
| DelegateVTable | IUnknown VTable（OK版とFail版） |
| mOkVTablePtr | QueryInterface成功用VTable |
| mFailVTablePtr | QueryInterface失敗用VTable |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 不正アクセス | 無効な関数ポインタ | AddressOfで有効な関数を指定 |
| シグネチャ不一致 | デリゲート型と関数シグネチャの不一致 | 適切なシグネチャの関数を定義 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（自動リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | なし |

### 配信時間帯

制限なし

## セキュリティ考慮事項

- NewDelegateと同様のセキュリティ考慮事項が適用される
- 構造体のライフタイム管理は呼び出し元の責任
- アプリケーション終了時はObjectPtrで参照解除が推奨

## 備考

- InitDelegateはDelegate構造体（8バイト）のみで動作し、LocalDelegate（12バイト）より軽量
- Delegate_OKQueryInterfaceとDelegate_FailQueryInterfaceでVTableを切り替え
- AddRefとReleaseは何もしない（Delegate_AddRefRelease）

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

Delegate構造体とInitDelegate用VTableを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | Delegate型（44-47行目）- pVTableとpfnのみの軽量構造体 |
| 1-2 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | DelegateVTable型（34-36行目）- Func(7)配列 |

**読解のコツ**: DelegateVTableはOK版（0-3）とFail版（4-7）の2セットを持つ。

#### Step 2: InitDelegate関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | InitDelegate関数（99-104行目） |

**主要処理フロー**:
- **100行目**: Init()で初期化（初回のみ）
- **101行目**: Struct.pfn = pfn（関数ポインタ設定）
- **102行目**: Struct.pVTable = mOkVTablePtr（OK VTable設定）
- **103行目**: ObjectPtr(InitDelegate) = VarPtr(Struct)（構造体アドレス返却）

#### Step 3: Delegate用VTable関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | Delegate_OKQueryInterface（204-207行目） |
| 3-2 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | Delegate_FailQueryInterface（209-212行目） |
| 3-3 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | Delegate_AddRefRelease（214-216行目） |

**主要処理フロー**:
- **206行目**: This.pVTable = mFailVTablePtr（次回QueryInterfaceは失敗）
- **214-216行目**: AddRefとReleaseは何もしない

#### Step 4: VTable初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | Init Sub内のDelegateVTable設定（161-173行目） |

**主要処理フロー**:
- **162行目**: .Func(0) = OKQueryInterface
- **163-164行目**: .Func(1), .Func(2) = AddRefRelease
- **165行目**: .Func(3) = DelegationCode
- **166-170行目**: .Func(4-7) = Fail版VTable

### プログラム呼び出し階層図

```
[呼び出し元クラス]
    │
    ├─ Private mDelegate As Delegate  ... 構造体宣言
    │
    └─ InitDelegate(mDelegate, AddressOf MyFunc)
           │
           ├─ Init() ... 初回のみVTable初期化
           │
           ├─ Struct.pfn = pfn
           │
           ├─ Struct.pVTable = mOkVTablePtr
           │
           └─ ObjectPtr = VarPtr(Struct)
                  │
                  ▼
           [delegate として使用]
                  │
                  └─ delegate.Invoke(args)
                         │
                         └─ DelegationCode経由
                                │
                                └─ MyFunc(args) 実行

    [クリーンアップ時]
           │
           └─ ObjectPtr(delegate) = vbNullPtr
                  │
                  └─ Releaseを呼ばずに参照解除
```

### データフロー図

```
[入力]                    [処理]                         [出力]

ByRef Struct        ───▶ InitDelegate         ───▶ IUnknown
(Delegate型)              │                         (構造体への参照)
                          ├─ pfn設定
AddressOf           ───▶ │
MyFunc                    └─ pVTable設定
(関数ポインタ)

delegate.Invoke     ───▶ DelegationCode        ───▶ MyFunc実行
(args)                    (マシンコード)              │
                                                      ▼
                                                  戻り値
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Delegation.bas | `Source/CorLib/System/Delegation.bas` | ソース | デリゲート作成・管理機能 |
| Ticker.cls | `Source/CorLib/System.Threading/Ticker.cls` | ソース | InitDelegate使用例（コールバック） |
