Awesome
PlayFabCSdk
Cross-Platform C/C++ PlayFab SDK.
This SDK currently supports the following platforms:
- Windows (Win32) x64
- GDK (Xbox and Windows)
- Linux (eg. Ubuntu 22.04 or Windows Subsystem for Linux)
- iOS
- macOS
- Android
- PlayStation 4/5 (private repo)
- Nintendo Switch (private repo)
For per-platform getting started guides and a complete list of available APIs, check out the online documentation.
To gain access to platforms supported through private repos, Request Access.
Requirements
Win32 and GDK
- A PlayFab developer account.
- Visual Studio 2022 installed (to build from source).
- (For GDK) Microsoft Game Development Kit installed.
iOS / macOS
- A PlayFab developer account.
- XCode IDE installed (to build from source).
Android
- A PlayFab developer account.
- Android Studio IDE installed (to build from source).
Project setup
Building with binary release package
Download the most recent release of the SDK from PlayFabCSdk releases.
Integrate PlayFab C SDK into your own project - Visual Studio (Win32 and GDK)
Each release package contains the required headers, binaries, and property sheet file (Win32 - PlayFabServicesSDK.Win32.props, GDK - PlayFabServicesSDK.GDK.props) that can be imported to your project to automatically add references.
You can import the props file manually by editing the .vcxproj files directly or by opening the Property Manager window in Visual Studio, right clicking on the project, and choosing Add Existing Property Sheet. After importing the appropriate props file, the headers should be available in your include path and references to the PlayFabServices library and its dependecies will be automatically added.
Note for GDK: It is possible for other GDK extensions such as the Xbox Services API or libHttpClient to be included as references automatically in projects. Any duplicate references will need to be removed manually. To do this, you can manage extensions in Visual Studio through Project -> Properties -> Gaming Desktop -> Gaming Extension Libraries.
Integrate PlayFab C SDK into your own project - XCode
Add binaries to your game
After getting your binaries by download or building from source you should be able to easily integrate them into your game/app.
Follow these instructions to add them:
- In XCode, navigate to your desired target and select it.
- Scroll down and in the "Frameworks, Libraries, and Embedded Content" section, click on the "+" sign.
- Search for your PlayFabServices / PlayFabCore / HttpClient binaries. (If you downloaded the xcframework file you can also select and it will automatically import whatever library is required independently if you're building for devices or simulator.)
Add Header search paths
Once binaries have been added you'll need to ensure that header search paths are also correctly set up.
- Navigate to your project.
- Click on "Build Settings" and then search for "Header Search Paths".
- Update the property value to include the SDK Headers. Please note that if you are using binaries from the downloaded release package you can simply reference the headers found in the include folder. However, if you are using binaries built from source you'll need to include the following paths:
PlayFab.C/Source/PlayFabServices/Include/Generated/ PlayFab.C/Source/PlayFabCore/Include/ PlayFab.C/Source/PlayFabCore/Include/Generated libHttpClient/Include
Integrate PlayFab C SDK into your own project - Android Studio
Add Shared Objects and Header files
- Using target_include_directories or another equivalent function, add the headers under "Include" from the PlayFab SDK release:
TARGET_INCLUDE_DIRECTORIES(
${PROJECT_NAME}
"Include"
)
If you're building from source, add this list of headers from the PlayFab SDK repository:
"PlayFab.C/Source/PlayFabServices/Include"
"PlayFab.C/Source/PlayFabServices/Include/Generated"
"PlayFab.C/Source/PlayFabCore/Include"
"PlayFab.C/Source/PlayFabCore/Include/Generated"
"libHttpClient/Include"
-
Using target_link_libraries or another equivalent function, link the locations of the .so files to your project.
For example:
set(PLAYFAB_SERVICES_PATH "[LOCATION OF YOUR FILE]/libPlayFabServices.Android.so")
set(PLAYFAB_CORE_PATH "[LOCATION OF YOUR FILE]/libPlayFabCore.Android.so")
set(LIBHTTPCLIENT_PATH "[LOCATION OF YOUR FILE]/libHttpClient.Android.so")
TARGET_LINK_LIBRARIES(
[YOUR PROJECT NAME]
${PLAYFAB_SERVICES_PATH}
${PLAYFAB_CORE_PATH}
${LIBHTTPCLIENT_PATH}
)
Add Android Archive files
-
Create a libs folder within app level Android project directory.
-
Copy the .aar files into the libs folder.
-
In app level build.gradle file, the one in the same directory as the libs folder, add these lines to the dependencies section. The second line is required as a dependency for libHttpClient.
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
Cloning source
This SDK depends on some external third-party open source libraries referenced as git submodules in directory /External
. Please make sure to use --recurse-submodules
command line parameter when cloning this git repo:
git clone --recurse-submodules https://github.com/PlayFab/PlayFabCSdk
or run the following commands to sync the content of submodules if the repo was cloned earlier without the --recurse-submodules
parameter:
git submodule update --init --recursive
Building from source for Windows and GDK
After cloning this repository and its submodules, you can build the libraries by opening the solution file PlayFab.C.vs2022.sln. That solution contains the PlayFabServices project, its dependencies, and a test app. After building, the binaries will be in a subdirectory within \Out.
Import Property Sheet (Windows and GDK)
To add a reference to the PlayFabServices projects to your own title, import the \Build\PlayFabServices.import.props file to your project. You can do this manually by editing the .vcxproj files directly or by opening the Property Manager window in Visual Studio, right clicking on the project, and choosing Add Existing Property Sheet. Note that the props file differs from the PlayFabServicesSDK.Win32.props mentioned above - it adds references to the projects instead of the prebuilt binaries.
Building (Windows and GDK)
To add a reference to the PlayFabServices projects to your own title, import the \Build\PlayFabServices.import.props file to your project. You can do this manually by editing the .vcxproj files directly or by opening the Property Manager window in Visual Studio, right clicking on the project, and choosing Add Existing Property Sheet. Note that the props file differs from the PlayFabServicesSDK.Win32.props mentioned above - it adds references to the projects instead of the prebuilt binaries.
PlayFabServicesTestApp
The included test app PlayFabServicesTestApp project will build as is, but some additional setup is required before it will run. The \Test\testTitleData.json file needs to be populated with a valid titleId, developer secret key, and connection string. Additionally, some APIs that are disabled by default need to be enabled via the PlayFab developer portal.
Even without making those changes, the PlayFabServicesTestApp source code serves as a good example of basic PlayFabServices SDK usage.
Building from source for Linux
After cloning this repository and its submodules, you can build the libraries by running
./Build/PlayFabServices.Linux/PlayFabServices_Linux.bash
For more detail on script options see PlayFabServices_Linux
Once built, the shared library can be used by adding this to your project's CMakeLists.txt:
find_package(PlayFabServicesLinux REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC PlayFabServicesLinux)
when running cmake, add this option and adjust the path as needed to tell it where package material can be found:
-D PlayFabServicesLinux_DIR=./Int/CMake/PlayFabServicesLinux
See .\Test\PlayFabServicesTestApp\Linux
for example CMake usage.
Building from source for iOS
After cloning this repository and its submodules, you can build the libraries by opening the workspace PlayFab.C.Apple.xcworkspace with XCode, then follow these steps:
- Select the scheme you want to build.
-
If you want to build PlayFabServices and PlayFabCore frameworks, select PlayFabServices_iOS/PlayFabServices_._macOS scheme and build. This scheme will generate the frameworks required to use PlayFab SDK:
- PlayFabCore_[iOS/macOS].framework
- PlayFabServices_[iOS/macOS].framework
- HttpClient_[iOS/macOS].framework
-
If you want to run the Test App, select the PlayFabServicesTestApp_._iOS/PlayFabServicesTestApp_macOS scheme, build and run the app.
- Select the run destination.
- For macOS you should be able to run on your own Mac, however, for iOS, you should select a Simulator running iOS 16.2 (or later) or you can run it on a physical devices attached to your Mac. Be aware that libraries built for simulators won't work on real devices and viceversa, so you need to choose the run destination based on where you want to run your app.
-
Grab the binaries. There are 2 different ways to do it:
-
Binaries will be placed in XCode default build directory which it's in the DerivedData folder usually located in:
~/Library/Developer/Xcode/DerivedData
In there, you can go to the target folder and navigate to the Build/Products folder to get all the binaries.
-
Another way to get to the binaries if you want to navigate directly to them:
- In the workspace navigation on XCode go to "Products" and expand it.
- Right-click on the framework generated and click "Show on Finder".
-
Building from source for Android
After cloning this repository and its submodules, you can build the libraries from the PlayFab.C/Build/PlayFabServices.Android.Workspace
directory by running:
./gradlew assembleFull
This will build the library in two configurations, debug and release, and two Android ABIs, arm64-v8a and x86_64.
If you wish to build separately for a single configuration, ABI, or both, the command can be freely mix and matched for this purpose.
Some examples of altering the command:
This builds for debug arm64-v8a and debug x86_64.
./gradlew assembleFullDebug
This builds for release x86_64.
./gradlew assemblex86_64Release
Init and Logging in
Headers
Include PFServices.h to get access to all included PlayFab functionality:
#include <playfab/services/PFServices.h>
Initialization
PlayFab initialization requires two function calls: PFServicesInitialize and PFServiceConfigCreateHandle. The result of this initialization is a PFServiceConfigHandle. You provide this handle to a subsequent login call, directing the call to the correct title in the PlayFab backend.
HRESULT hr = PFServicesInitialize(nullptr); // Add your own error handling when FAILED(hr) == true
PFServiceConfigHandle serviceConfigHandle{ nullptr };
hr = PFServiceConfigCreateHandle(
"https://ABCDEF.playfabapi.com", // PlayFab API endpoint - obtained in the Game Manager
"ABCDEF", // PlayFab Title id - obtained in the Game Manager
&serviceConfigHandle);
Logging in
Once you have a PFServiceConfigHandle, you can use it to make a player login call. In the SDK, use a PFAuthenticationLoginWith*Async method like PFAuthenticationLoginWithCustomIDAsync. This function allows you to log in a player to PlayFab using a custom string, which is useful during development and testing.
After making a login call, you can check the status of the call with XAsyncGetStatus. The status starts as E_PENDING and changes to S_OK after the call completes successfully. If the call fails for some reason, the status reflects that failure. Error handling on all PlayFab Services calls works this way.
Along with an S_OK result, you get back a PFEntityHandle. You use this handle to make subsequent PlayFab calls as the logged in player. It includes any material required to authenticate with the PlayFab service as that player.
PFAuthenticationLoginWithCustomIDRequest request{};
request.createAccount = true;
request.customId = "player1";
XAsyncBlock async{};
HRESULT hr = PFAuthenticationLoginWithCustomIDAsync(serviceConfigHandle, &request, &async); // Add your own error handling when FAILED(hr) == true
hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
std::vector<char> loginResultBuffer;
PFAuthenticationLoginResult const* loginResult;
size_t bufferSize;
hr = PFAuthenticationLoginWithCustomIDGetResultSize(&async, &bufferSize);
loginResultBuffer.resize(bufferSize);
PFEntityHandle entityHandle{ nullptr };
hr = PFAuthenticationLoginWithCustomIDGetResult(&async, &entityHandle, loginResultBuffer.size(), loginResultBuffer.data(), &loginResult, nullptr);
Service Calls
After logging the player in, you can now make calls to the PlayFab backend. Here's an example of a call to get files stored in PlayFab for the current player.
Getting the EntityKey
One thing that can be useful for some calls to PlayFab is knowing the PFEntityKey of the player. Once you have a PFEntityToken, you can retrieve a PFEntityKey with PFEntityGetEntityKey.
PFEntityKey const* pEntityKey{};
std::vector<char> entityKeyBuffer;
size_t size{};
HRESULT hr = PFEntityGetEntityKeySize(entityHandle, &size); // Add your own error handling when FAILED(hr) == true
entityKeyBuffer.resize(size);
hr = PFEntityGetEntityKey(entityHandle, entityKeyBuffer.size(), entityKeyBuffer.data(), &pEntityKey, nullptr);
Calling GetFiles
All PlayFab calls follow a similar pattern of preparing the request object, making the call (using the PFEntityHandle from login), creating an object to receive the response, and then calling a GetResult function to fill the newly created container.
XAsyncBlock async{};
PFDataGetFilesRequest requestFiles{};
requestFiles.entity = pEntityKey;
HRESULT hr = PFDataGetFilesAsync(entityHandle, &requestFiles, &async); // Add your own error handling when FAILED(hr) == true
hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
size_t resultSize;
hr = PFDataGetFilesGetResultSize(&async, &resultSize);
std::vector<char> getFilesResultBuffer(resultSize);
PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
hr = PFDataGetFilesGetResult(&async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
Clean up
When your game is ready to shut down or you need to clean up PlayFab for some other reason, ensure you close all open handles and call PFServicesUninitializeAsync.
PFEntityCloseHandle(entityHandle);
entityHandle = nullptr;
PFServiceConfigCloseHandle(serviceConfigHandle);
serviceConfigHandle = nullptr;
XAsyncBlock async{};
HRESULT hr = PFServicesUninitializeAsync(&async); // Add your own error handling when FAILED(hr) == true
hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
Async API pattern
The PlayFab Services SDK follows an Asynchronous Programming Model. This programming model involves the use of Tasks and Task Queues provided by the XAsync library. While it does introduce some complexity, it also brings a high degree of control over asynchronous operations.
This example shows how to make an asynchronous call to PFDataGetFilesAsync.
auto async = std::make_unique<XAsyncBlock>();
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // take ownership of XAsyncBlock
size_t resultSize;
HRESULT hr = PFDataGetFilesGetResultSize(async, &resultSize);
if (SUCCEEDED(hr))
{
std::vector<char> getFilesResultBuffer(resultSize);
PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
PFDataGetFilesGetResult(async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
}
};
PFDataGetFilesRequest requestFiles{};
requestFiles.entity = m_pEntityKey;
HRESULT hr = PFDataGetFilesAsync(m_entityHandle, &requestFiles, async.get());
if (SUCCEEDED(hr))
{
async.release(); // at this point, the callback will be called so release the unique ptr
}
Error handling
Completed XAsync operations return HTTP status codes. An error status code manifests as a failure HRESULT such as HTTP_E_STATUS_NOT_FOUND when calling XAsyncGetStatus() or one of the PF*Get() APIs.
To see detailed error messages returned by the service see the next section on debugging. These detailed error messages can be useful during development to better understand how the PlayFab service reacts to requests from the client.
Debugging
The easiest way to see the results and debug any calls in the PlayFab Services SDK is to enable Debug Tracing. Enabling debug tracing allows you to both see the results in the debugger output window and hook the results into your game's own logs.