Setting up a worker using the C API
Using the C example project
The C example project is a fairly minimal example of project structure and build configuration for workers using the C API. It is likely the best project to start from, in addition to reading this documentation page.
Requirements
The C worker API works with any C compiler that supports the ANSI C standard, or any other language which is designed to work with C libraries. We compile the native libraries which target at least the following toolchains and platforms:
- Windows: Microsoft Visual Studio 2015 Update 3 and above.
- macOS: OS X Yosemite (10.10) and above.
- Linux: gcc 5.4.0 with
GLIBCXX_3.4.21
and above.
On Windows, if you choose to use a worker package which has been compiled with the
/MD
or/MDd
flags (multithreaded dynamic, and multithreaded dynamic debug), then any system which uses these libraries (including client systems) will also require Visual C++ Redistributable for Visual Studio 2015.
Obtaining the SDK
Similar to other SDKs, you obtain the SDK through worker packages, our package management framework. Assuming you have a worker set up with a worker configuration, you can obtain the relevant worker package as follows:
Assuming that
worker_dir
is<project_root>/workers/<your_worker>
, add the following configuration within<worker_dir>/spatialos_worker_packages.json
to download the header files and libraries to<worker_dir>/dependencies/worker_sdk
:{ "targets": [ { "path": "dependencies/worker_sdk", "type": "worker_sdk", "packages": [ { "name": "<package_name>" } ] } ] }
There are packages of the C API compiled for different platforms and configurations, including both static and dynamic libraries, the latter being useful for loading into other languages. The options for
<package_name>
are currently:Static:
c-static-x86_64-msvc_md-win32
: Windows 64-bit compiled using VS 2015 (with /MD runtime).c-static-x86_64-msvc_mdd-win32
- Windows 64-bit compiled using VS 2015 (with /MDd runtime).c-static-x86_64-msvc_mt-win32
- Windows 64-bit compiled using VS 2015 (with /MT runtime).c-static-x86_64-msvc_mtd-win32
- Windows 64-bit compiled using VS 2015 (with /MTd runtime).c-static-x86_64-clang_libcpp-macos
- macOS 64-bit compiled using Xcode 8.c-static-x86_64-gcc_libstdcpp-linux
- Linux 64-bit compiled using gcc 5.4.0 with the libstdc++ standard library.c-static-x86_64-gcc_libstdcpp_pic-linux
- Linux 64-bit compiled as position-independent code using gcc 5.4.0 with the libstdc++ standard library.
Dynamic:
c-dynamic-x86_64-msvc_md-win32
- Windows 64-bit compiled using VS 2015 (with /MD runtime).c-dynamic-x86_64-msvc_mdd-win32
- Windows 64-bit compiled using VS 2015 (with /MDd runtime).c-dynamic-x86_64-msvc_mt-win32
- Windows 64-bit compiled using VS 2015 (with /MT runtime).c-dynamic-x86_64-msvc_mtd-win32
- Windows 64-bit compiled using VS 2015 (with /MTd runtime).c-dynamic-x86_64-clang_libcpp-macos
- macOS 64-bit compiled using Xcode 8.c-dynamic-x86_64-gcc_libstdcpp-linux
- Linux 64-bit compiled using gcc 5.4.0 with the libstdc++ standard library.c-dynamic-x86_64-gcc_libstdcpp_pic-linux
- Linux 64-bit compiled as position-independent code using gcc 5.4.0 with the libstdc++ standard library.
Plug-in Bundle (macOS only):
c-bundle-x86_64-clang_libcpp-macos
- macOS 64-bit compiled using Xcode 8.
You can specify multiple packages at once as multiple entries in the
targets
array with different paths if desired. For example, if building a worker using C and C++, you can download both the Multithreaded Dynamic (MD) and Multithreaded Dynamic Debug (MDd) packages, and point the MSVC project to link against the different packages depending on the configuration (Debug / Release). We can also specify packages for macOS and Linux so these can be used when building on other platforms. In this example, thespatialos_worker_packages.json
will look similar to:{ "targets": [ { "path": "dependencies/worker_sdk/windows/debug", "type": "worker_sdk", "packages": [ { "name": "c-static-x86_64-msvc_mdd-win32", "platform": "windows" } ] }, { "path": "dependencies/worker_sdk/windows/release", "type": "worker_sdk", "packages": [ { "name": "c-static-x86_64-msvc_md-win32", "platform": "windows" } ] }, { "path": "dependencies/worker_sdk/macos", "type": "worker_sdk", "packages": [ { "name": "c-static-x86_64-clang_libcpp-macos", "platform": "macos" } ] }, { "path": "dependencies/worker_sdk/linux", "type": "worker_sdk", "packages": [ { "name": "c-static-x86_64-gcc_libstdcpp-linux", "platform": "linux" } ] } ] }
In a command prompt / terminal, either
cd
to<worker_dir>
and runspatial package unpack
(which is done automatically byspatial worker build
if unpack dependencies is specified in thebuild.json
).This will unpack the worker package specified above into the sub-directory. The downloaded worker package will be compatible with the SpatialOS SDK version used for your application (specified in
<root>/spatialos.json
undersdk_version
).
Compiling and linking
The way that you’ll be using the contents of the worker packages depends entirely on which language that will be using the C API. Usually, you’d include / read the header files in some way to understand the API, then link or load against the static or dynamic library (compiled as native code). Each worker package specified above contains the following structure:
<worker_package>/include/improbable
- This folder contains two header files:c_worker.h
- The worker API, including connecting to SpatialOS and interacting with snapshots.c_schema.h
- The schema API, used to serialize / deserialize components and commands.
<worker_package>/lib
- This folder only exists in static packages, and contains static libraries for the C API and its dependencies. On non-Windows platforms, you’ll need to ensure that these libraries are linked in the following order:worker
,grpc++
,grpc
,gpr
,protobuf
,RakNetLibStatic
,ssl
,z
(orzlibstatic.lib
on Windows), or you may get linker errors.<worker_package>/worker.dll
- This file only exists in dynamic packages. This file is the dynamic library which is designed to be loaded by a dynamic language such as Python (or linked to a native executable using the dynamic linker). This file is namedlibworker.dylib
orworker.framework
in the macOS packages, andlibworker.so
in the Linux packages.
Building a managed worker assembly.
After building a project, a certain directory structure is expected when
uploading an assembly.
Therefore, the steps of the Build task for your worker (within
spatialos.<worker_type>.worker.json
) should:
Create a zip file containing the worker binary with a name matching the value for the
artifact_name
specified in the managed worker configuration, undermanaged
thenlinux
.Place the zip file in
<project_root>/build/assembly/worker/
, so it is picked up when uploading an assembly duringspatial cloud upload <assembly name>
.
SpatialOS runs managed workers as part of a cloud deployment in a Linux environment running Ubuntu 16.04.2 LTS. Therefore, you need to build a binary that can be executed in this environment. If you are developing on Windows or macOS, we suggest installing Ubuntu 16.04.2 LTS inside a virtual machine using VirtualBox, and making use of the experimental Linux support. This is not required for local deployments during development: just for cloud deployments.