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

# Using multiple GameInput API versions in one application

> Learn how to use QueryInterface to combine different GameInput API versions, such as v0 and v4, in the same application.

Each GameInput API version, v0 through v4, defines its own set of COM interfaces. The GameInput runtime implements every version on the same underlying objects, so a single object, such as a device, has a v0 interface, a v4 interface, and an interface for each version in between. To switch an object from one version to another, call [QueryInterface](https://docs.xbox.com/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface\(refiid_void\)) on it.

This lets you:

* Add v4 features to an application that's built on an earlier API version, such as v0, without migrating the whole application at once.
* Call SDKs, middleware, or engine plug-ins that were built against an earlier version of GameInput, even when the rest of your application uses v4.

## Supported API versions

A GameInput runtime supports every API version that's lower than or equal to its own major version. For example, with the GameInput 4.0 runtime installed, every GameInput object implements the v0, v1, v2, v3, and v4 interfaces, and your application can use any combination of them.

| Installed runtime | API versions that you can use |
| - | - |
| 4.x | v0, v1, v2, v3, v4 |
| 3.x | v0, v1, v2, v3 |
| 2.x | v0, v1, v2 |
| 1.x | v0, v1 |

If you request an API version that's newer than the installed runtime, `QueryInterface` and [GameInputInitialize](https://docs.xbox.com/reference/input/gameinput/functions/gameinputinitialize.md) fail with `E_NOINTERFACE`. The highest API version that your application uses determines the minimum runtime version that it requires.

On PC, the installed runtime is the GameInput redistributable or a runtime that you deploy with your game. For more information, see [GameInput NuGet package](https://docs.xbox.com/build/core-features/common/input/overviews/input-nuget.md) and [GameInput sideloading](https://docs.xbox.com/build/core-features/common/input/overviews/input-agility-redistributable.md). On XBOX, the runtime is included with the GDK, and you can also deploy a newer runtime with your game. For more information, see [GameInput on XBOX consoles](https://docs.xbox.com/build/core-features/common/input/overviews/input-xbox.md).

## Set up your project

For new implementations, use the headers and `GameInput.lib` from the latest [Microsoft.GameInput](https://www.nuget.org/packages/Microsoft.GameInput) NuGet package. In the package, `<GameInput.h>` is the latest header, and each earlier header is in a versioned folder, such as `<v0/GameInput.h>` or `<v2/GameInput.h>`. The library exports [GameInputInitialize](https://docs.xbox.com/reference/input/gameinput/functions/gameinputinitialize.md), which creates GameInput for any API version that you request.

Libraries from earlier releases, such as the one in the GDK, also continue to work. For more information, see [Keep an earlier library](#keep-an-earlier-library).

### Include the v0 header

Starting with v1, each GameInput header declares its types in a versioned namespace, such as `GameInput::v4`. The v0 header declares its types in the global namespace instead. To use the v0 header together with the latest header, put the following boilerplate in a header of your own, such as `GameInputV0.h`:

```cpp theme={null}
// GameInputV0.h: declares the v0 API in the GameInput::v0 namespace
#pragma once

#include <windows.h>
#include <GameInput.h>

// The v0 header isn't namespaced; its dependencies are already included above.
namespace GameInput::v0
{
    // Prevent the legacy typedefs from finding interfaces declared by the latest header.
    struct IGameInput;
    struct IGameInputReading;
    struct IGameInputDevice;
    struct IGameInputDispatcher;
    struct IGameInputForceFeedbackEffect;
    struct IGameInputRawDeviceReport;

    #include <v0/GameInput.h>
}
```

This header works as follows:

* It includes the latest `<GameInput.h>` first. This declares the latest API in its own namespace, and includes the Windows and COM headers that the v0 header depends on, so the v0 header doesn't include them again inside the namespace.
* The forward declarations make the typedefs in the v0 header declare new interfaces in `GameInput::v0`, instead of referring to interfaces that the latest header already declared.
* Including `<v0/GameInput.h>` inside the namespace moves every v0 type, enumeration, and constant into `GameInput::v0`, such as `GameInput::v0::IGameInput` and `GameInput::v0::GameInputKindGamepad`.

In your v0 source files, include `GameInputV0.h` instead of `<GameInput.h>`, and add `using namespace GameInput::v0;` so that the existing code can keep using unqualified names. Any source file that includes `GameInputV0.h` can also use the latest API by its full name, such as `GameInput::v4::IGameInput`.

## Example: Add v4 features to a v0 application

You don't need to rewrite your v0 code to start using v4 features. Keep the v0 code in its own source files, and put new v4 code in separate source files. Pass GameInput objects between the two as `IUnknown*`, and have each side call `QueryInterface` for the version that it needs.

### Existing v0 code

The following v0 code creates GameInput and reads the gamepad. Compared to the original v0 code, only three things change:

* It includes `GameInputV0.h` instead of `<GameInput.h>`.
* It creates GameInput by calling `GameInputInitialize` with the v0 IID, because the latest library doesn't export the v0 `GameInputCreate` function.
* It calls the new v4 code when the A button is pressed.

```cpp theme={null}
// LegacyInput.cpp: existing code that uses the v0 API
#include "GameInputV0.h"

using namespace GameInput::v0;

// Implemented in NewInputFeatures.cpp.
void SetControllerColor(IUnknown* device);

IGameInput* g_gameInput = nullptr;

HRESULT InitializeInput()
{
    return GameInput::v4::GameInputInitialize(__uuidof(IGameInput), reinterpret_cast<void**>(&g_gameInput));
}

void UpdateGamepad()
{
    IGameInputReading* reading = nullptr;
    if (SUCCEEDED(g_gameInput->GetCurrentReading(GameInputKindGamepad, nullptr, &reading)))
    {
        GameInputGamepadState state;
        reading->GetGamepadState(&state);

        if (state.buttons & GameInputGamepadA)
        {
            IGameInputDevice* device = nullptr;
            reading->GetDevice(&device);
            SetControllerColor(device);
            device->Release();
        }

        reading->Release();
    }
}
```

### New v4 code

The new source file includes the v4 header and calls `QueryInterface` on the device that the v0 code passes in. It then changes the color of the controller's center light with [IGameInputDevice::SetLightingColor](https://docs.xbox.com/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_setlightingcolor.md) and [IGameInputDevice::ApplyLightingColors](https://docs.xbox.com/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_applylightingcolors.md), which are new in v4. If the device doesn't have a center light, the call is ignored.

```cpp theme={null}
// NewInputFeatures.cpp: new code that uses the v4 API
#include <windows.h>
#include <v4/GameInput.h>

using namespace GameInput::v4;

void SetControllerColor(IUnknown* legacyDevice)
{
    IGameInputDevice* device = nullptr;

    // Fails with E_NOINTERFACE if the installed runtime is older than 4.0.
    if (SUCCEEDED(legacyDevice->QueryInterface(IID_PPV_ARGS(&device))))
    {
        device->SetLightingColor({ 0, 255, 0 }, GameInputLightingGroupCenterLight);
        device->ApplyLightingColors();
        device->Release();
    }
}
```

If `QueryInterface` fails, the installed runtime doesn't support v4. Your v0 code keeps working, and your application can skip the v4 features.

When all of your code uses v4, you can remove `GameInputV0.h` and the `QueryInterface` calls.

### Keep an earlier library

If you continue to link a library from an earlier release, such as the one in the GDK, your existing v0 code doesn't need to change at all. Keep including the v0 header from that release and calling `GameInputCreate`. That call is forwarded to the installed runtime, so when the runtime is 4.0 or later, the object that it returns also implements the v4 interfaces, and the new v4 code shown earlier works without changes.

Earlier libraries don't export `GameInputInitialize`. Get v4 interfaces only by calling `QueryInterface`, and don't call the v4 `GameInputCreate`, which calls `GameInputInitialize`.

## Rules for switching between versions

Interfaces from different API versions have the same names, such as `IGameInput` and `IGameInputDevice`, but they're different types with different methods. A pointer to a v0 interface isn't a pointer to a v4 interface, even though both refer to the same object.

> [!NOTE]
>
> Casting isn't the same as calling `QueryInterface`. Always use `QueryInterface` to get an interface for a different API version. Never use `static_cast`, `reinterpret_cast`, or a C-style cast to convert between versions. A cast compiles, but calling a method through the converted pointer can call the wrong method, which leads to undefined behavior.

```cpp theme={null}
GameInput::v0::IGameInputDevice* legacyDevice = /* ... */;

// Wrong: compiles, but calls the wrong methods at run time.
auto badDevice = reinterpret_cast<GameInput::v4::IGameInputDevice*>(legacyDevice);

// Correct: asks the object for its v4 interface.
GameInput::v4::IGameInputDevice* device = nullptr;
HRESULT hr = legacyDevice->QueryInterface(IID_PPV_ARGS(&device));
```

Also keep these rules in mind:

* **Don't include another GameInput header after the v0 header.** The v0 header defines its error codes, such as `GAMEINPUT_E_DEVICE_DISCONNECTED`, as macros, and those macros break the declarations in any GameInput header that's included after it. `GameInputV0.h` follows this rule by including the latest header first.
* **Returned objects use the version that you called.** For example, `GetDevice` on a v4 reading returns a v4 device, and a device callback that's registered with the v4 `IGameInput` receives v4 devices. Call `QueryInterface` before you pass these objects to code that uses another version.
* **Each `QueryInterface` call adds a reference.** Release the returned pointer when you no longer need it, just like any other COM interface pointer.
* **Check the result.** When you request a newer API version, a failure means that the installed runtime doesn't support that version.
* **The v0 types in `GameInputV0.h` are separate C++ types.** `GameInput::v0::IGameInput` and the global `IGameInput` from `<v0/GameInput.h>` alone describe the same interface, but C++ treats them as different types. If existing code or another library declares functions with the global v0 types, call those functions from a source file that includes only `<v0/GameInput.h>`.

## Call SDKs that use an earlier API version

Some SDKs, middleware, and engine plug-ins are built against a specific GameInput API version and expect GameInput interfaces of that version. Your application can use a newer version and still call these components. Call `QueryInterface` to get the version that the component expects, and pass that pointer.

Put the call in a source file that includes the same GameInput header that the component uses. In the following example, `ThirdPartySdk.h` declares `ThirdPartySdkInitialize(GameInput::v2::IGameInput*)`, and the rest of the application passes its GameInput object as `IUnknown*`:

```cpp theme={null}
// SdkBridge.cpp: calls an SDK that was built against the v2 API
#include <windows.h>
#include <v2/GameInput.h>
#include "ThirdPartySdk.h"

HRESULT InitializeThirdPartySdk(IUnknown* gameInputObject)
{
    GameInput::v2::IGameInput* gameInput = nullptr;
    HRESULT hr = gameInputObject->QueryInterface(IID_PPV_ARGS(&gameInput));
    if (SUCCEEDED(hr))
    {
        ThirdPartySdkInitialize(gameInput);
        gameInput->Release();
    }

    return hr;
}
```

The same approach works in the other direction. If a component gives your application a GameInput object of an earlier version, call `QueryInterface` on it to get the v4 interface.

Because every version is implemented by the same object, the SDK and your application share devices, readings, and state. The SDK's API version must also be lower than or equal to the installed runtime version.

## See also

[GameInput API versioning](https://docs.xbox.com/build/core-features/common/input/overviews/input-versioning.md)\
[GameInput NuGet package](https://docs.xbox.com/build/core-features/common/input/overviews/input-nuget.md)\
[GameInput sideloading](https://docs.xbox.com/build/core-features/common/input/overviews/input-agility-redistributable.md)\
[GameInputInitialize](https://docs.xbox.com/reference/input/gameinput/functions/gameinputinitialize.md)\
[GameInput API reference](https://docs.xbox.com/reference/input/gameinput/gameinput_members.md)


## Related topics

- [GameInput API Versioning](https://docs.xbox.com/build/core-features/common/input/overviews/input-versioning.md)
- [GameInput on XBOX consoles](https://docs.xbox.com/build/core-features/common/input/overviews/input-xbox.md)
- [GameInputInitialize](https://docs.xbox.com/reference/input/gameinput/functions/gameinputinitialize.md)
- [GameInputCreate](https://docs.xbox.com/reference/input/gameinput/functions/gameinputcreate.md)
- [Combining GameInput with existing input stacks](https://docs.xbox.com/build/core-features/common/input/porting/input-porting.md)
