Skip to content

C++ Client API

The C++ API can be used to build multiplayer clients for games and applications, including those made with a C++ game engine. The API is derived from the reference API implementation in Java and supports all of its features.

The API is distributed in source form with very few dependencies (also included) and a simple build system based on CMake.

Download the API zip file from the SmartFoxServer website and extract the folder corresponding to your platform of choice, then follow the instructions below.

Prerequisites

  • A C++17 compiler: Clang, GCC or MSVC
  • CMake 3.16 or higher (cmake.org)
  • Windows, macOS or Linux

API documentation

Consult the API DocC

Building

The API is built with CMake. From the root of this package, configure an out-of-source build directory and build it:

mkdir build
cd build
cmake ../src
cmake --build . --parallel 8

The --parallel option builds with more than one job at a time, which is much faster. Set the number to the count of CPU cores of your machine. Without this option the build uses one job only.

The build type is Release if you do not set one. For a debug build pass -DCMAKE_BUILD_TYPE=Debug to the first command.

Windows and Visual Studio

For this to work you need at least Visual Studio Community (2019 16.4 or higher) with the "Desktop development with C++" workload installed.

The same four steps apply, but the last one must specify the build type. Visual Studio keeps all build types in one project, so it ignores -DCMAKE_BUILD_TYPE and you select the type at build time with --config:

mkdir build
cd build
cmake ../src
cmake --build . --config Release --parallel 8
Without --config Visual Studio makes a Debug build. Use --config Debug if that is what you want.

The configure step also writes a Visual Studio solution, build/SFS3_CppClient.sln. You can open it in the IDE and build from there instead of the command line. It is a normal CMake product: you do not have to use it, and you must not edit it by hand, because the next cmake ../src writes it again.

Where the libraries are

The build makes three static libraries:

  • sfs_client — the API itself
  • sfs_compression — the bundled compression code
  • sfs_mbedtls — the bundled TLS code, for HTTPS

On macOS and Linux they are in the build/ folder, with the names libsfs_client.a, libsfs_compression.a and libsfs_mbedtls.a.

On Windows with Visual Studio each build type has its own folder, so the files are in build/Release/ (or build/Debug/), with the names sfs_client.lib, sfs_compression.lib and sfs_mbedtls.lib. The .pdb files next to them hold the debug symbols.

Link all three into your application. Add src/ and src/third_party/ to your include paths.

macOS

On macOS and iOS you must also link the CoreFoundation and Security system frameworks.

Windows with MinGW

On Windows with MinGW you must link ws2_32 and mswsock; with Visual Studio these are linked automatically.

If your project uses CMake too, there is a simpler way. Add this package to your build and link the target: CMake then applies the include paths and the system libraries for you.

add_subdirectory(path/to/SFS3_API_Cpp/src sfs3)
target_link_libraries(myGame PRIVATE sfs_client)

Basic example

The following is a simple C++ client that connects to SmartFoxServer 3 running on the local machine. Below we show how to build it with CMake, or with Visual Studio on Windows.

#include "ConfigData.h"
#include "SmartFox.h"
#include "event/SFSEvent.h"
#include "log/Log.h"
#include "requests/LoginRequest.h"
#include <chrono>
#include <thread>

using namespace sfs3;

int main(void)
{
    SmartFox sfs;
    ConfigData cfg;

    cfg.zone = "Playground";

    sfs.addEventListener(event::SFSEvent::CONNECTION, [&cfg, &sfs](const event::ApiEvent& e)
    {
        auto& evt = static_cast<const event::Connection&>(e);

        if (!evt.success)
        {
            log::warn("Connection failed: {}", evt.errMessage.value_or("unknown reason"));
            return;
        }

        log::info("Connected to {}:{}", cfg.host, cfg.port);
        sfs.send(requests::LoginRequest { "" });
    });

    sfs.addEventListener(event::SFSEvent::LOGIN, [](const event::ApiEvent& e)
    {
        auto& evt = static_cast<const event::Login&>(e);
        log::info("Logged in as: {}", evt.mySelf->getName());
    });

    sfs.addEventListener(event::SFSEvent::LOGIN_ERROR, [](const event::ApiEvent& e)
    {
        auto& evt = static_cast<const event::LoginError&>(e);
        log::info("Login failed: {}", evt.errorMessage);
    });

    log::info("C++ API version: {}", sfs.getVersion());
    sfs.connect(cfg);

    while(true)
    {
        sfs.processEvents();
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

The looping call to processEvents() is necessary. By default the API collects the events and gives them to you on the thread that calls this method. Without the loop events are never handled. This is the typical style used in most single-threaded game engines, from Raylib to Unity or Unreal Engine.

Building the test with CMake

  • Create a folder to store the example.
  • Create a new file called app.cpp and copy the example into it.
  • Create a new file called CMakeLists.txt and copy the following into it:
cmake_minimum_required(VERSION 3.16)
project(SFS3TestApp LANGUAGES C CXX)

add_subdirectory(../SFS3_API_Cpp_v3.1.0_beta/src sfs3)

add_executable(SFS3TestApp app.cpp)
target_link_libraries(SFS3TestApp PRIVATE sfs_client)

Change the add_subdirectory directive so that it points to the src/ folder of your pre-built API. In our case we saved the example in a folder at the same level as the API folder. Also double check it matches the name of the API folder, which changes on every release.

Finally:

mkdir build
cd build
cmake ..
cmake --build .

Building the test with Visual Studio (Windows)

Step 1 - Create the console project

In Visual Studio select File → New → Project and select Console App for C++.

In the toolbar set the configuration to Release and the platform to x64.

Step 2 - Set the project properties

Right-click the project in Solution Explorer and select Properties, or press Alt+F7.

At the top of the window set:

  • Configuration: All Configurations
  • Platform: x64

Set All Configurations before you type anything. Visual Studio keeps a separate value of every property for Debug and for Release. If you fill the pages with only Debug selected, the Release build finds nothing and stops with error C1083: Cannot open include file.

Now set the five properties below.

2.1 Language standard

Configuration Properties → General → C++ Language Standard

Select ISO C++17 Standard (/std:c++17).

2.2 Header folders

C/C++ → General → Additional Include Directories

Open the drop-down and select <Edit...>. Add two lines:

C:\SFS3_API_Cpp\src
C:\SFS3_API_Cpp\src\third_party

The small toolbar in that dialog has a button that adds a new line. A ... button then appears at the end of the line and opens a folder browser.

The Macro>> button at the bottom lists variables such as $(SolutionDir). A path written with a macro keeps working when the project moves.

2.3 Preprocessor definitions

C/C++ → Preprocessor → Preprocessor Definitions

Select <Edit...> and add these three. Keep the ones already there.

_WIN32_WINNT=0x0A00
WIN32_LEAN_AND_MEAN
NOMINMAX

The API is built with these definitions. Your project needs the same ones, because the networking headers change shape without them.

2.4 Library folder

Linker → General → Additional Library Directories

C:\SFS3_API_Cpp\build\$(Configuration)

$(Configuration) becomes Release or Debug on its own. One line then serves both build types.

2.5 The libraries

Linker → Input → Additional Dependencies

Select <Edit...> and add the three names, one per line:

sfs_client.lib
sfs_compression.lib
sfs_mbedtls.lib

This field has no folder browser. You type the names. The linker looks for them in the folders of step 2.4.

You do not need ws2_32 or mswsock. Visual Studio links the networking libraries on its own.

Select OK.

Step 3 - Build and run

Build with Ctrl+Shift+B and run with Ctrl+F5.