> ## 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.

# Ciclo de vida do SDK

> Inicialize, configure e desligue o SDK do PlayFab Services para C na ordem correta, incluindo hooks de memória, Core e configuração de serviço.

Esta página aborda a sequência completa de inicialização e desligamento do SDK do PlayFab Services. Todo título segue o mesmo padrão geral: configurar hooks opcionais, inicializar o Core, criar uma configuração de serviço, inicializar o Services, realizar o trabalho e, em seguida, desligar na ordem inversa.

## Sequência de inicialização

A inicialização tem quatro etapas. A primeira é opcional; as três restantes são obrigatórias.

```
PFMemSetFunctions (optional)  →  PFInitialize  →  PFServiceConfigCreateHandle  →  PFServicesInitialize
```

### Etapa 1: definir hooks de memória personalizados (opcional)

Se o seu título usa um alocador de memória personalizado, chame [**PFMemSetFunctions**](/pt-BR/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) antes de qualquer outra API do PlayFab. Isso direciona todas as alocações de memória do SDK para seus próprios retornos de chamada `alloc` e `free`.

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

<Info>
  [**PFMemSetFunctions**](/pt-BR/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) deve ser chamado antes de [**PFInitialize**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfinitialize). Ele não pode ser chamado novamente depois que os hooks forem definidos.
</Info>

Se você não precisar de gerenciamento de memória personalizado, ignore esta etapa. O SDK usa as rotinas de alocação padrão.

### Etapa 2: inicializar o PlayFab Core

[**PFInitialize**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfinitialize) configura o estado global do SDK, incluindo a camada HTTP e a fila de tarefas em segundo plano. A assinatura exata varia de acordo com a plataforma.

#### Windows, Linux, iOS e macOS

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

Passe um **XTaskQueueHandle** se quiser controlar qual fila processa o trabalho em segundo plano. Passe `nullptr` para usar a fila padrão do pool de threads.

#### Android

No Android, você também deve fornecer a Java VM e o contexto do aplicativo para que o SDK possa inicializar o libHttpClient:

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

<Note>
  Se você não chamar **PFInitialize** explicitamente, [**PFServicesInitialize**](/pt-BR/services/playfab/api-references/c/pfservices/functions/pfservicesinitialize) o chamará internamente com os parâmetros padrão. Isso é adequado para a maioria dos títulos. No entanto, se você estiver usando hooks de memória personalizados por meio de **PFMemSetFunctions**, **deverá** chamar **PFInitialize** por conta própria; caso contrário, [**PFServicesInitialize**](/pt-BR/services/playfab/api-references/c/pfservices/functions/pfservicesinitialize) inicializará o Core antes que seus hooks de memória entrem em vigor, e o SDK usará as rotinas de alocação padrão.
</Note>

### Etapa 3: criar uma configuração de serviço

[**PFServiceConfigCreateHandle**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle) cria um identificador que informa ao SDK qual título e qual ponto de extremidade do PlayFab usar. Você encontrará ambos os valores no [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);
```

O **PFServiceConfigHandle** retornado é necessário para todas as chamadas de login subsequentes.

### Etapa 4: inicializar o PlayFab Services

**PFServicesInitialize** configura a camada Services (Inventory, Leaderboards, Friends e assim por diante) sobre o Core.

#### Windows, Linux, iOS e macOS

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

O parâmetro é reservado para uso futuro; passe `nullptr`.

#### Android

No Android, passe um struct **HCInitArgs** que contenha a Java VM e o contexto do aplicativo:

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

Depois que essa chamada for bem-sucedida, o SDK estará pronto. Você poderá fazer login de jogadores e fazer chamadas de serviço.

## Ciclo de vida de PFServiceConfigHandle

Um **PFServiceConfigHandle** é um identificador com contagem de referências. O SDK gerencia seu tempo de vida interno por meio da contagem de referências, mas você é responsável por fechar todos os identificadores que possui.

| Função | Descrição |
| - | - |
| [**PFServiceConfigCreateHandle**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle) | Cria um novo identificador. A contagem de referências inicial é 1. |
| [**PFServiceConfigDuplicateHandle**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigduplicatehandle) | Incrementa a contagem de referências e retorna um segundo identificador. Ambos os identificadores devem ser fechados de forma independente. |
| [**PFServiceConfigCloseHandle**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigclosehandle) | Decrementa a contagem de referências. Quando ela chega a 0, a configuração é destruída. |
| [**PFServiceConfigGetAPIEndpoint**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggetapiendpoint) | Recupera a cadeia de caracteres do ponto de extremidade da API. Chame [**PFServiceConfigGetAPIEndpointSize**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggetapiendpointsize) primeiro para determinar o tamanho do buffer. |
| [**PFServiceConfigGetTitleId**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggettitleid) | Recupera a cadeia de caracteres da ID do título. Chame [**PFServiceConfigGetTitleIdSize**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfiggettitleidsize) primeiro para determinar o tamanho do buffer. |

### Duplicando um identificador

Use [**PFServiceConfigDuplicateHandle**](/pt-BR/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigduplicatehandle) quando precisar compartilhar uma configuração de serviço entre componentes que gerenciam seus próprios tempos de vida:

```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);
```

## Sequência de desligamento

O desligamento é o inverso da inicialização. Você deve desinicializar o Services antes do Core, e ambas as chamadas são assíncronas.

```
Close handles  →  PFServicesUninitializeAsync  →  PFUninitializeAsync
```

### Etapa 1: fechar todos os identificadores abertos

Antes de desmontar o SDK, feche todos os **PFEntityHandle** e **PFServiceConfigHandle** que você possui:

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

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

### Etapa 2: desinicializar o Services

[**PFServicesUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfservices/functions/pfservicesuninitializeasync) desmonta a camada Services. Aguarde a conclusão antes de prosseguir.

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

### Etapa 3: desinicializar o Core

Depois que a limpeza do Services terminar, chame [**PFUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) para desmontar o Core:

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

<Note>
  Se você não chamou **PFInitialize** explicitamente, pode ignorar **PFUninitializeAsync**. Nesse caso, [**PFServicesUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfservices/functions/pfservicesuninitializeasync) cuida da limpeza do Core automaticamente. No entanto, se você chamou **PFInitialize** por conta própria, deverá chamar [**PFUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) por conta própria.
</Note>

## Exemplo completo

Este exemplo mostra o ciclo de vida completo, da inicialização ao desligamento, em um título do 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);
}
```

## Erros comuns

| Erro | O que acontece | Correção |
| - | - | - |
| Chamar [**PFMemSetFunctions**](/pt-BR/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) depois de [**PFInitialize**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfinitialize) | A chamada falha. Os hooks de memória só podem ser definidos antes da inicialização. | Mova [**PFMemSetFunctions**](/pt-BR/services/playfab/api-references/c/pfplatform/functions/pfmemsetfunctions) para a primeiríssima chamada do PlayFab no seu programa. |
| Chamar [**PFUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) antes de [**PFServicesUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfservices/functions/pfservicesuninitializeasync) | Comportamento indefinido. O Core é desmontado enquanto o Services ainda depende dele. | Sempre desinicialize o Services primeiro, aguarde a conclusão e então desinicialize o Core. |
| Esquecer de chamar [**PFUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync) após um [**PFInitialize**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfinitialize) explícito | Há vazamento de recursos do Core. A fila em segundo plano e a camada HTTP não são limpas. | Se você chamou [**PFInitialize**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfinitialize), deverá chamar [**PFUninitializeAsync**](/pt-BR/services/playfab/api-references/c/pfcore/functions/pfuninitializeasync). |
| Não aguardar a conclusão da desinicialização assíncrona | O processo pode ser encerrado enquanto a limpeza ainda está em andamento, causando falhas ou travamentos. | Use `XAsyncGetStatus(async, true)` ou um retorno de chamada de **XAsyncBlock** para aguardar a conclusão. |
| Vazamento de **PFServiceConfigHandle** ou **PFEntityHandle** | Os recursos com contagem de referências não são liberados e podem impedir um desligamento limpo. | Feche todos os identificadores que você criar ou duplicar antes de chamar a desinicialização. |

## Confira também

* [Início rápido: Win32](/pt-BR/services/playfab/sdks/c/quickstart-win32)
* [Início rápido: Windows](/pt-BR/services/playfab/sdks/c/quickstart-gdk)
* [Rastreamento de depuração](/pt-BR/services/playfab/sdks/c/tracing)
* [Modelo de programação assíncrona](https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/system/overviews/async-programming-model)


## Related topics

- [Identificadores de entidade](/pt-BR/services/playfab/sdks/c/entity-handles.md)
- [Ciclo de vida de um servidor multijogador](/pt-BR/services/playfab/multiplayer/servers/multiplayer-game-server-lifecycle.md)
- [Ciclo de vida dos builds de servidores multijogador](/pt-BR/services/playfab/multiplayer/servers/multiplayer-build-lifecycle.md)
- [Ciclo de vida de uma região de build de servidor multijogador](/pt-BR/services/playfab/multiplayer/servers/multiplayer-build-region-lifecycle.md)
- [SDK do PlayFab Services - Event Pipeline](/pt-BR/services/playfab/sdks/c/event-pipeline/eventpipeline.md)
