> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK ライフサイクル

> メモリフック、Core、およびサービス構成を含め、PlayFab Services C SDK を正しい順序で初期化、構成、およびシャットダウンします。

このページでは、PlayFab Services SDK の完全な起動とシャットダウンのシーケンスについて説明します。すべてのタイトルは同じ高レベルパターンに従います: オプションのフックを構成し、Core を初期化し、サービス構成を作成し、Services を初期化し、作業を行い、その後逆順でシャットダウンします。

## 初期化シーケンス

初期化には 4 つのステップがあります。最初はオプションで、残りの 3 つは必須です。

```
PFMemSetFunctions (オプション)  →  PFInitialize  →  PFServiceConfigCreateHandle  →  PFServicesInitialize
```

### ステップ 1: カスタムメモリフックの設定 (オプション)

タイトルがカスタムメモリアロケーターを使用する場合、他の PlayFab API の前に [**PFMemSetFunctions**](/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) を呼び出します。これにより、すべての SDK メモリ割り当てが独自の `alloc` および `free` コールバックを経由するようになります。

```cpp theme={null}
PFMemoryHooks hooks{};
hooks.alloc = MyAllocFunction;
hooks.free = MyFreeFunction;
HRESULT hr = PFMemSetFunctions(&hooks);
```

<Info>
  [**PFMemSetFunctions**](/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) は [**PFInitialize**](/services/playfab/api-references/c/pfcore/functions/pfinitialize) の前に呼び出す必要があります。フックが設定された後に再度呼び出すことはできません。
</Info>

カスタムメモリ管理が不要な場合は、このステップをスキップしてください。SDK はデフォルトの割り当てルーチンを使用します。

### ステップ 2: PlayFab Core の初期化

[**PFInitialize**](/services/playfab/api-references/c/pfcore/functions/pfinitialize) は、HTTP レイヤーとバックグラウンドタスクキューを含む SDK のグローバル状態を設定します。正確なシグネチャはプラットフォームによって異なります。

#### Windows、Linux、iOS、および macOS

```cpp theme={null}
HRESULT hr = PFInitialize(nullptr); // Uses a default threadpool queue
```

バックグラウンドの作業を処理するキューを制御したい場合は **XTaskQueueHandle** を渡します。デフォルトのスレッドプールキューを使用するには `nullptr` を渡します。

#### Android

Android では、SDK が libHttpClient を初期化できるように、Java VM とアプリケーションコンテキストも提供する必要があります:

```cpp theme={null}
HRESULT hr = PFInitialize(nullptr, javaVm, applicationContext);
```

<Note>
  **PFInitialize** を明示的に呼び出さない場合、[**PFServicesInitialize**](/services/playfab/api-references/c/pfservices/functions/pfservicesinitialize) が内部でデフォルトパラメーターで呼び出します。ほとんどのタイトルではこれで問題ありません。ただし、**PFMemSetFunctions** を介してカスタムメモリフックを使用している場合は、**PFInitialize** を自分で呼び出す**必要があります**。そうしないと、[**PFServicesInitialize**](/services/playfab/api-references/c/pfservices/functions/pfservicesinitialize) がメモリフックが有効になる前に Core を初期化し、SDK はデフォルトの割り当てルーチンを代わりに使用します。
</Note>

### ステップ 3: サービス構成の作成

[**PFServiceConfigCreateHandle**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle) は、対象とする PlayFab タイトルとエンドポイントを SDK に伝えるハンドルを作成します。両方の値は [Game Manager](https://developer.playfab.com) で見つけることができます。

```cpp theme={null}
PFServiceConfigHandle serviceConfigHandle{ nullptr };
HRESULT hr = PFServiceConfigCreateHandle(
    "https://ABCDEF.playfabapi.com",    // API endpoint from Game Manager
    "ABCDEF",                           // Title ID from Game Manager
    &serviceConfigHandle);
```

返される **PFServiceConfigHandle** は、後続のすべてのログイン呼び出しに必要です。

### ステップ 4: PlayFab Services の初期化

**PFServicesInitialize** は Services レイヤー (Inventory、Leaderboards、Friends など) を Core の上に設定します。

#### Windows、Linux、iOS、および macOS

```cpp theme={null}
HRESULT hr = PFServicesInitialize(nullptr);
```

このパラメーターは将来使用するために予約されています。`nullptr` を渡してください。

#### Android

Android では、Java VM とアプリケーションコンテキストを含む **HCInitArgs** 構造体を渡します:

```cpp theme={null}
HRESULT hr = PFServicesInitialize(nullptr, initArgs);
```

この呼び出しが成功すると、SDK は準備完了です。プレイヤーをログインさせ、サービス呼び出しを行うことができます。

## PFServiceConfigHandle のライフサイクル

**PFServiceConfigHandle** は参照カウントされたハンドルです。SDK は参照カウントによって内部の寿命を管理しますが、所有するすべてのハンドルを閉じる責任があります。

| 関数                                                                                                                                | 説明                                                                                                                                                                                        |
| --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**PFServiceConfigCreateHandle**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle)       | 新しいハンドルを作成します。初期参照カウントは 1 です。                                                                                                                                                             |
| [**PFServiceConfigDuplicateHandle**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigduplicatehandle) | 参照カウントをインクリメントし、2 つ目のハンドルを返します。両方のハンドルを独立して閉じる必要があります。                                                                                                                                    |
| [**PFServiceConfigCloseHandle**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigclosehandle)         | 参照カウントをデクリメントします。0 に達すると、構成は破棄されます。                                                                                                                                                       |
| [**PFServiceConfigGetAPIEndpoint**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggetapiendpoint)   | API エンドポイント文字列を取得します。バッファーサイズを決定するには、最初に [**PFServiceConfigGetAPIEndpointSize**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggetapiendpointsize) を呼び出します。 |
| [**PFServiceConfigGetTitleId**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggettitleid)           | タイトル ID 文字列を取得します。バッファーサイズを決定するには、最初に [**PFServiceConfigGetTitleIdSize**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggettitleidsize) を呼び出します。            |

### ハンドルの複製

独自の寿命を管理するコンポーネント間でサービス構成を共有する必要がある場合は、[**PFServiceConfigDuplicateHandle**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigduplicatehandle) を使用します:

```cpp theme={null}
PFServiceConfigHandle duplicatedHandle{ nullptr };
HRESULT hr = PFServiceConfigDuplicateHandle(serviceConfigHandle, &duplicatedHandle);

// Both handles are now valid and must be closed separately
PFServiceConfigCloseHandle(duplicatedHandle);
PFServiceConfigCloseHandle(serviceConfigHandle);
```

## シャットダウンシーケンス

シャットダウンは初期化の逆です。Core の前に Services を非初期化する必要があり、両方の呼び出しは非同期です。

```
ハンドルを閉じる  →  PFServicesUninitializeAsync  →  PFUninitializeAsync
```

### ステップ 1: すべての開いているハンドルを閉じる

SDK を解体する前に、所有するすべての **PFEntityHandle** と **PFServiceConfigHandle** を閉じます:

```cpp theme={null}
PFEntityCloseHandle(entityHandle);
entityHandle = nullptr;

PFServiceConfigCloseHandle(serviceConfigHandle);
serviceConfigHandle = nullptr;
```

### ステップ 2: Services の非初期化

[**PFServicesUninitializeAsync**](/services/playfab/api-references/c/pfservices/functions/pfservicesuninitializeasync) は Services レイヤーを解体します。続行する前に完了を待ちます。

```cpp theme={null}
XAsyncBlock asyncServices{};
HRESULT hr = PFServicesUninitializeAsync(&asyncServices);
hr = XAsyncGetStatus(&asyncServices, true); // Blocking wait
```

### ステップ 3: Core の非初期化

Services のクリーンアップが完了したら、Core を解体するために [**PFUninitializeAsync**](/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) を呼び出します:

```cpp theme={null}
XAsyncBlock asyncCore{};
HRESULT hr = PFUninitializeAsync(&asyncCore);
hr = XAsyncGetStatus(&asyncCore, true); // Blocking wait
```

<Note>
  **PFInitialize** を明示的に呼び出さなかった場合、**PFUninitializeAsync** をスキップできます。その場合、[**PFServicesUninitializeAsync**](/services/playfab/api-references/c/pfservices/functions/pfservicesuninitializeasync) が Core のクリーンアップを自動的に処理します。ただし、**PFInitialize** を自分で呼び出した場合は、[**PFUninitializeAsync**](/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) を自分で呼び出す必要があります。
</Note>

## 完全な例

この例は、Windows タイトルで初期化からシャットダウンまでの完全なライフサイクルを示しています:

```cpp theme={null}
#include <playfab/services/PFServices.h>

void RunPlayFab()
{
    //
    // Optional: set custom memory hooks
    //
    PFMemoryHooks hooks{};
    hooks.alloc = MyAllocFunction;
    hooks.free = MyFreeFunction;
    HRESULT hr = PFMemSetFunctions(&hooks);

    //
    // Initialize Core
    //
    hr = PFInitialize(nullptr);

    //
    // Create a service configuration
    //
    PFServiceConfigHandle serviceConfigHandle{ nullptr };
    hr = PFServiceConfigCreateHandle(
        "https://ABCDEF.playfabapi.com",
        "ABCDEF",
        &serviceConfigHandle);

    //
    // Initialize Services
    //
    hr = PFServicesInitialize(nullptr);

    //
    // Log in a player (Windows example using XUser)
    //
    PFAuthenticationLoginWithXUserRequest request{};
    request.createAccount = true;
    request.user = userHandle;

    XAsyncBlock asyncLogin{};
    hr = PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, &request, &asyncLogin);
    hr = XAsyncGetStatus(&asyncLogin, true);

    size_t bufferSize{};
    hr = PFAuthenticationLoginWithXUserGetResultSize(&asyncLogin, &bufferSize);

    std::vector<char> loginResultBuffer(bufferSize);
    PFAuthenticationLoginResult const* loginResult{};
    PFEntityHandle entityHandle{ nullptr };
    hr = PFAuthenticationLoginWithXUserGetResult(
        &asyncLogin, &entityHandle,
        loginResultBuffer.size(), loginResultBuffer.data(),
        &loginResult, nullptr);

    //
    // ... make service calls ...
    //

    //
    // Shutdown: close handles first
    //
    PFEntityCloseHandle(entityHandle);
    entityHandle = nullptr;

    PFServiceConfigCloseHandle(serviceConfigHandle);
    serviceConfigHandle = nullptr;

    //
    // Shutdown: uninitialize Services, then Core
    //
    XAsyncBlock asyncServices{};
    hr = PFServicesUninitializeAsync(&asyncServices);
    hr = XAsyncGetStatus(&asyncServices, true);

    XAsyncBlock asyncCore{};
    hr = PFUninitializeAsync(&asyncCore);
    hr = XAsyncGetStatus(&asyncCore, true);
}
```

## よくある間違い

| 間違い                                                                                                                                                                                                                                 | 何が起きるか                                                | 修正                                                                                                                                                                                                              |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**PFInitialize**](/services/playfab/api-references/c/pfcore/functions/pfinitialize) の後に [**PFMemSetFunctions**](/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) を呼び出す                                   | 呼び出しが失敗します。メモリフックは初期化前にのみ設定できます。                      | [**PFMemSetFunctions**](/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) をプログラムの最初の PlayFab 呼び出しに移動します。                                                                               |
| [**PFServicesUninitializeAsync**](/services/playfab/api-references/c/pfservices/functions/pfservicesuninitializeasync) の前に [**PFUninitializeAsync**](/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) を呼び出す | 未定義の動作。Services がまだ依存している状態で Core が解体されます。            | 常に最初に Services を非初期化し、完了を待ってから Core を非初期化します。                                                                                                                                                                   |
| 明示的な [**PFInitialize**](/services/playfab/api-references/c/pfcore/functions/pfinitialize) の後に [**PFUninitializeAsync**](/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) を呼び出し忘れる                           | Core リソースがリークします。バックグラウンドキューと HTTP レイヤーがクリーンアップされません。 | [**PFInitialize**](/services/playfab/api-references/c/pfcore/functions/pfinitialize) を呼び出した場合は、[**PFUninitializeAsync**](/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) を呼び出す必要があります。 |
| 非同期の非初期化の完了を待たない                                                                                                                                                                                                                    | クリーンアップがまだ進行中の間にプロセスが終了する可能性があり、クラッシュやハングを引き起こします。    | `XAsyncGetStatus(async, true)` または **XAsyncBlock** コールバックを使用して完了を待ちます。                                                                                                                                          |
| **PFServiceConfigHandle** または **PFEntityHandle** をリークする                                                                                                                                                                             | 参照カウントされたリソースが解放されず、クリーンなシャットダウンを妨げる可能性があります。         | 非初期化を呼び出す前に、作成または複製したすべてのハンドルを閉じます。                                                                                                                                                                             |

## 関連項目

* [クイックスタート: Win32](/services/playfab/sdks/c/quickstart-win32)
* [クイックスタート: Windows](/services/playfab/sdks/c/quickstart-gdk)
* [デバッグトレース](/services/playfab/sdks/c/tracing)
* [非同期プログラミングモデル](https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/system/overviews/async-programming-model)


## Related topics

- [エンティティハンドル](/ja-jp/services/playfab/sdks/c/entity-handles.md)
- [マルチプレイヤー サーバーのライフサイクル](/ja-jp/services/playfab/multiplayer/servers/multiplayer-game-server-lifecycle.md)
- [マルチプレイヤー サーバー ビルドのライフサイクル](/ja-jp/services/playfab/multiplayer/servers/multiplayer-build-lifecycle.md)
- [マルチプレイヤー サーバー ビルド リージョンのライフサイクル](/ja-jp/services/playfab/multiplayer/servers/multiplayer-build-region-lifecycle.md)
- [Game Saves の概要](/ja-jp/build/core-features/common/game-save/game-saves-overview.md)
