Introducing XPPL

Posted by daemotron on Fri, Sep 22, 2023

Are you tired of (re-)writing the same boilerplace code for every X-Plane plugin project — over and over again? Well, at least that’s how I felt when I started my fourth or fifth plugin. Sure, I reused a lot of my boilerplate code, but with every project, I refined and enhanced it. Backporting those changes to older plugins became a tedious task though; therefore I started the X-Plane Plugin Library (XPPL).

The name is slightly misleading — XPPL is not a shared library (like a Windows .dll or Unix .so file), but rather a code library, providing a modular collection of source code files which can be embedded into any C or C++ project. The way the code library is organized allows you to cherry-pick only code you really need for your plugin project.

What Can XPPL Do?

Currently, XPPL is relatively light and provides some basic functionality:

  • xppl.h: macros for min / max comparisons, marking unused arguments, and crashing the application
  • xppl_alloc.h: malloc, calloc and realloc implementations with integrated success checking and failure logging. Requires the xppl_common module.
  • xppl_config.h: enhance your plugin by a configuration file. Requires the xppl_common and xppl_config modules.
  • xppl_float.h: equality checks for different floating point types, using epsilon and ULP. Requires the xppl_common module.
  • xppl_int.h: activate 128 bit integer (if available) and provide abs macro for integers.
  • xppl_log.h: configurable logging. Requires the xppl_common module.
  • xppl_path.h: platform-independent dirname, create path, create path recursively and check for path existence implementation. Requires the xppl_common module.
  • xppl_test.h: basic unit test framework without third-party dependencies. Requires the xppl_common and xppl_test modules.

How To Use XPPL

In this example, we’re using XPPL’s logging functionality in a simple, barebone X-Plane plugin (as described in X-Plane Plugin Boilerplate. In a first step, let’s add XPPL as Git submodule:

1git submodule add https://github.com/daemotron/xppl.git

If you don’t track your plugin with Git, you can alternatively check out the XPPL repository into your project directory:

1git clone https://github.com/daemotron/xppl.git 

Either method will end with a directory called xppl, sitting at the same level as your src and SDK directories. Next, we need to tell CMake to include XPPL into the plugin build. Insert the following snippet into your CMakeLists.txt:

1# Detect XPPL
2get_filename_component(XPPL_PATH "./xppl/" ABSOLUTE)
3message("-- Detecting XPPL path")
4
5if(NOT EXISTS ${XPPL_PATH})
6    message(FATAL_ERROR "Missing XPPL folder: ${XPPL_PATH}")
7endif(NOT EXISTS ${XPPL_PATH})

Now we have to make sure CMake picks up the required XPPL module(s):

 1# Include files
 2include_directories ("./src")
 3include_directories ("${SDK_PATH}")
 4include_directories ("${SDK_PATH}/CHeaders/XPLM")
 5include_directories ("${SDK_PATH}/CHeaders/Wrappers")
 6include_directories ("${SDK_PATH}/CHeaders/Widgets")
 7include_directories ("${XPPL_PATH}/include")
 8
 9file(GLOB_RECURSE PROJECT_SOURCES "src/*.c")
10file(GLOB_RECURSE XPPL_COMMON_SOURCES "xppl/xppl_common/*.c")
11
12set(SOURCES ${PROJECT_SOURCES} ${XPPL_COMMON_SOURCES})

Further modules could be added using the same scheme. Now let’s take a look at the plugin code itself (main.c):

 1#include <string.h>
 2
 3#include <XPLMPlugin.h>
 4#include <XPLMUtilities.h>
 5
 6#include <xppl.h>
 7#include <xppl_log.h>
 8
 9
10PLUGIN_API int
11XPluginStart(char *outName, char *outSig, char *outDesc)
12{
13    strcpy(outName, "DaemoPlug");
14    strcpy(outSig, "net.daemotron.plugin");
15    strcpy(outDesc, "The uber cool plugin that does absolutely nothing.");
16
17    xppl_log_init(XPLMDebugString, XPPL_LOG_DEBUG, "DAEMOPLUG");
18    xppl_log_info("DaemoPlug version 1337");
19
20    return 1;
21}
22
23
24PLUGIN_API void
25XPluginStop(void)
26{
27    xppl_log_destroy();
28}

That’s all — now the simple plugin can use the various xppl_log functions, which will automagically dump the log output to X-Plane’s log.txt.

How About libacfutils?

Let me be clear about this: XPPL is not meant to be a replacement for Saso Kiselkov’s excellent libacfutils. His library goes far beyond what XPPL is (and likely ever will) meant to be. XPPL is designed to be (and remain) a lightweight code collection, facilitating the most basic boilerplate tasks.