Home

Awesome

bindbc-sfml

This project provides both static and dynamic D bindings to versions 2.0 – 2.5 of the CSFML libraries, which in turn are the official C bindings to the SFML game and multimedia libraries written in C++. This package is intended as a replacement of DerelictSFML2.

About CSFML

This documentation describes how to use BindBC-SFML. As the maintainer of this library, I do not provide instructions on using CSFML. However, since these are direct bindings to the CSFML API, then the following quote from the CSFML download page applies (documentation link added by me for convenience):

Since the CSFML API is similar to SFML, there's no tutorial for it; but you can follow the C++ tutorials available on this website, and adapt them to the C API very easily.

The CSFML download packages include the C API documentation so that you can easily see how to translate the C++ examples to C, which in turn will be an almost direct translation to D. (In the future, I intend to create a D tutorial series that will use BindBC-SFML.)

Usage

By default, BindBC-SFML is configured to compile as dynamic bindings that are not -betterC compatible. The dynamic bindings have no link-time dependency on the CSFML libraries, so the CSFML shared libraries must be manually loaded at runtime. When configured as static bindings, there is a link-time dependency on the CSFML libraries—either the static libraries or the appropriate files for linking with shared libraries on your system (see below).

When using DUB to manage your project, the static bindings can be enabled via a DUB subConfiguration statement in your project's package file. -betterC compatibility is also enabled via subconfigurations.

To use any of the supported CSFML libraries, add BindBC-SFML as a dependency to your project's package file and include the appropriate version for any of the CSFML libraries you want to use. Note that the CSFML System library is always loaded, and when the CSFML Graphics library is configured, the CSFML Window library will be loaded automatically.

As an example, the following is configured to use the Audio, Graphics, System, and Window libraries via dynamic bindings that are not -betterC compatible:

dub.json

"dependencies": {
    "bindbc-sfml": "~>1.1.0",
},
"versions": [
    "SFML_Audio",
    "SFML_Graphics"
],

dub.sdl

dependency "bindbc-sfml" version="~>1.1.0"
versions "SFML_Audio" "SFML_Graphics"

The dynamic bindings

The dynamic bindings require no special configuration when using DUB to manage your project. There is no link-time dependency. At runtime, the CSFML shared libraries are required to be on the shared library search path of the user's system. On Windows, this is typically handled by distributing the CSFML DLLs with your program. On other systems, it usually means installing the SFML runtime libraries through a package manager.

To load the shared libraries, you need to call the appropriate load function. Each CSFML library binding provides load functions that return a binding-specific value indicating either that the library failed to load (it couldn't be found) or that one or more symbols failed to load, or that a version number that matches a global constant based on the compile-time configuration.

There is also a global loadSFML function that will load all configured CSFML libraries, and which returns true on success or false on failure. This is possible due to the fact that all of the CSFML libraries are part of the same versioned release package. In other words, all of the CSFML libraries you distribute with your application should be from the same release, e.g. CSFML 2.2 or CSFML 2.5. Never mix different CSFML library versions in the same program.

Note that it is not necessary to load the CSFML System library unless you intend to call any functions from the System API. When using the CSFML Graphics library, the same holds true for the CSFML Window library; the Graphics library is dependent on the Window library, and both shared libraries need to be in the same directory (along with the System shared library, upon which all the CSFML libraries depend), but it is not necessary to load the Window library if you do not need to call any of its functions.

/*
 The package modules for any CSFML libraries you have configured will be imported
 with this single import statement. In the case of the configuration example
 above, the Audio, Graphics, System, and Window package modules will be imported.
*/
import bindbc.sfml;

/*
 This version attempts to load the CSFML System library and all configured CSFML libraries using well-known variations of the library names for the host system. Note that when the Graphics library is configured, the Window library is also
 automatically configured, so `loadSFML` will attempt to load it as well.
*/
if(!loadSFML()) {
    /*
     A CSFML library failed to load. The error handling API in bindbc-loader
     can be used to fetch the error messages.
    */
}

/*
 This version attempts to load a specific CSFML library individually. This allows for more nuanced error handling, and avoids the loading of the System and, in this case, Window libraries when you don't need to use them.
*/
SFMLSupport ret = loadSFMLGraphics();
if(ret != sfmlSupport) {
    /*
     sfmlSupport is the compile-time constant representing the CSFML version that was configured, e.g., `SFMLSupport.sfml200`, `SFMLSupport.sfml220`, etc. If the load was successful, then the returned value should match the `sfmlSupport` value. If the load failed, the returned value will be one of `SFMLSupport.noLibrary` or `SFMLSupport.badLibrary`.
    */
    if(ret == SFMLSupport.noLibrary) {
        /*
         The system failed to load the library. Usually this means that either the library or one of its dependencies could not be found.
        */
    }
    else if(ret == SFMLSupport.badLibrary) {
        /*
         This indicates that the system was able to find and successfully load the library, but one or more symbols the binding expected to find was missing. This usually indicates that the loaded library is of a lower API version than the binding was configured to load, e.g., a CSFML 2.0 library loaded by a CSFML 2.5 configuration.

         For many C libraries, this is perfectly fine and the application can continue as long as none of the missing functions are called. Unfortunately, for CSFML, this can be problematic, as the maintainer sometimes changes the signature of functions from one minor version to the next. (This is addressed later in this documentation.)
        */
    }
}

/*
 This version attempts to load a specific CSFML library using a user-supplied file name.
 Usually, the name and/or path will be platform specific, as in this example
 which attempts to load `csfml-graphics.dll` from the `libs` subdirectory, relative
 to the executable, only on Windows. It has the same return values as the version above.
*/
version(Windows) {
    auto ret = loadSFMLGraphics("libs/csfml-graphics.dll");
    if(ret != sfmlSupport) {
        // Error handling as above.
    }
}

By default, each CSFML library binding is configured to compile bindings for version 2.0.0 the C library. This ensures the widest level of compatibility at runtime. This behavior can be overridden by using via specific identifiers. It is recommended that you always select the minimum version you require and no higher. In this example, the CSFML dynamic bindings (for each CSFML library you intend to use) is compiled to support CSFML version 2.5.0:

dub.json

"dependencies": {
    "bindbc-sfmll": "~>1.1.0"
},
"versions": [
    "SFML_Audio",
    "SFML_Graphics",
    "SFML_250",
],

dub.sdl

dependency "bindbc-sfml" version="~>1.1.0"
versions "SFML_Audio" "SFML_Graphics" "SFML_250"

Following are the supported CSFML library versions and the corresponding version identifiers to pass to the compiler.

Library VersionVersion Identifier
SFML 2.0.0Default
SFML 2.1.0SFML_210
SFML 2.2.0SFML_220
SFML 2.3.0SFML_230
SFML 2.4.0SFML_240
SFML 2.5.0SFML_250

[!NOTE]
Unlike the main SFML libraries, CSFML does not tend to have patch releases. This means, for example, that CSFML 2.5.0 is compatible with SFML 2.5.0, SFML 2.5.1, and any future SFML 2.5.x releases. As a result, the CSFML_VERSION_PATCH constant is always 0.

[!NOTE]
There is no difference in the public API between CSFML 2.0 and CSFML 2.1.

Version mismatch

Many C libraries have versioning schemes such that minor version releases, e.g. 2.0 vs 2.1, are still compatible. In that case, a dynamic binding can load e.g. a 2.0 library with a 2.1 binding and, as long as no 2.1 functions are called, run as normal. With SFML, this is actually only true with versions 2.0 and 2.1.

Beginning in CSFML 2.2 and continuing in later versions, some function signatures were changed from the previous versions. Due to the nature of dynamic loading, this will not break library loading when, say, a 2.0 library is loaded by a 2.5 binding. However, it will cause undefined behavior (most likely a crash) if an affected function is called.

For that reason, it is recommended that if you configure BindBC-SFML with version SFML_230 or higher, you always treat a load function return value of SFMLSupport.badLibrary as an irrecoverable failure and do not attempt to continue with the lower library version.

If you insist on supporting older CSFML versions than the one you've configured, you'll need to be aware of the changes. In some cases, the type of one or more parameters, or of the return value, was changed, In other cases, parameters were added. Some of the changes might be harmless (like changing a return type from int to float), or harmless 64-bit builds (like changing a parameter or return type from uint to size_t), but the rest can cause issues.

These are the functions you need to watch out for, the version in which the change was made, and the nature of the change:

VersionFunction NameChange
SFML_220sfFont_getKerningReturn type (void to sfBool)
SFML_220sfFont_getLineSpacingReturn type (void to sfBool)
SFML_220sfSoundRecorder_startReturn type (void to sfBool)
SFML_230sfCircleShape_getPointParameter type (uint to size_t)
SFML_230sfCircleShape_getPointCountReturn type (uint to size_t)
SFML_230sfCircleShape_setPointCountParameter type (uint to size_t)
SFML_230sfConvexShape_getPointParameter type (uint to size_t)
SFML_230sfConvexShape_getPointCountReturn type (uint to size_t)
SFML_230sfConvexShape_setPointCountParameter type (uint to size_t)
SFML_230sfRectangleShape_getPointParameter type (uint to size_t)
SFML_230sfRectangleShape_getPointCountReturn type (uint to size_t)
SFML_230sfRenderTexture_drawPrimitivesParameter type (uint to size_t)
SFML_230sfRenderWindow_drawPrimitivesParameter type (uint to size_t)
SFML_230sfShader_createFromStreamAdditional parameter
SFML_230sfShape_getPointParameter type (uint to size_t)
SFML_230sfShape_getPointCountReturn type (uint to size_t)
SFML_230sfSoundBuffer_createFromSamplesParameter type (size_t to sfUint64)
SFML_230sfSoundBuffer_getSampleCountReturn type (size_t to sfUint64)
SFML_230sfVertexArray_getVertexCountReturn type (uint to size_t)
SFML_230sfVertexArray_getVertexParameter type (uint to size_t)
SFML_230sfVertexArray_resizeParameter type (uint to size_t)
SFML_240sfContext_setActiveReturn type (void to sfBool)
SFML_240sfTcpListener_listenAdditional parameter
SFML_240sfUdpSocket_bindAdditional parameter
SFML_240sfSoundBufferRecorder_startReturn type (void to sfBool)
SFML_250sfFtp_uploadAdditional parameter

The static bindings

The static bindings have a link-time dependency on either the shared or static CSFML libraries. On Windows, you can link with the static libraries or, to use the DLLs, the import libraries. On other systems, you can link with either the static libraries or directly with the shared libraries.

This requires the CSFML development packages be installed on your system at compile time. When linking with the static libraries, there is no runtime dependency on CSFML. When linking with the shared libraries, the runtime dependency is the same as the dynamic bindings, the difference being that the shared libraries are no longer loaded manually—loading is handled automatically by the system when the program is launched.

[!NOTE]
The CSFML binary distributions on the CSFML download page do not include static libraries. The Windows packages contain import libraries, meaning the DLLs will still be required at runtime. To obtain the static libraries, you will either have to build them yourself or find prebuilt libraries somewhere else. I am unaware of anywhere that provides the CSFML static libraries for download, so if you do find them somewhere, please let me know.

Enabling the static bindings can be done in two ways.

Via the compiler's -version switch or DUB's versions directive

Pass the BindSFML_Static version to the compiler and link with the appropriate libraries. Note that BindSFML_Static will also enable the static binding for all configured CSFML libraries.

When using the compiler command line or a build system that doesn't support DUB, this is the only option. The -version=BindSFML_Static option should be passed to the compiler when building your program. All of the required C libraries, as well as the BindBC-SFML and bindbc-loader static libraries, must also be passed to the compiler on the command line or via your build system's configuration.

[!NOTE]
The version identifierentifier BindBC_Static can be used to configure all of the official BindBC packages used in your program. (i.e. those maintained in the BindBC GitHub organisation) Some third-party BindBC packages may support it as well.

For example, when using the static bindings for the SFML Audio and Graphics packages with DUB:

dub.json

"dependencies": {
    "bindbc-sfml": "~>1.1.0"
},
"versions": ["BindSFML_Static", "SFML_Audio", "SFML_Graphics"],
"libs": ["csfml-audio", "csfml-graphics"]

dub.sdl

dependency "bindbc-sfml" version="~>1.1.0"
versions "BindSFML_Static" "SFML_Audio" "SFML_Graphics"
libs "csfml-audio"  "csfml-graphics"

Note that if you wished to call any CSFML System or Window functions, the csdml-system and csfml-window libraries would need to be linked as well.

Via DUB subconfigurations

Instead of using DUB's versions directive, a subConfiguration can be used. Enable the static subconfiguration for the BindBC-SFML dependency:

dub.json

"dependencies": {
    "bindbc-sfml": "~>1.1.0"
},
"subConfigurations": {
    "bindbc-sfml": "static"
},
"versions": [
    "SFML_Audio",
    "SFML_Graphics",
],
"libs": ["csfml-audio", "csfml-graphics"]

dub.sdl

dependency "bindbc-sfml" version="~>1.1.0"
subConfiguration "bindbc-sfml" "static"
versions "SFML_Audio" "SFML_Graphics"
libs "csfml-audio"  "csfml-graphics"

Note that if you wished to call any CSFML System or Window functions, the csdml-system and csfml-window libraries would need to be linked as well.

-betterC support

-betterC support is enabled via the dynamicBC and staticBC subconfigurations, for dynamic and static bindings respectively. To enable the static bindings with -betterC support:

dub.json

"dependencies": {
    "bindbc-sfml": "~>1.1.0"
},
"subConfigurations": {
    "bindbc-sfml": "staticBC"
},
"versions": [
    "SFML_Audio",
    "SFML_Graphics",
],
"libs": ["csfml-audio", "csfml-graphics"]

dub.sdl

dependency "bindbc-sfml" version="~>1.1.0"
subConfiguration "bindbc-sfml" "staticBC"
versions "SFML_Audio" "SFML_Graphics"
libs "csfml-audio"  "csfml-graphics"

Note that if you wished to call any CSFML System or Window functions, the csdml-system and csfml-window libraries would need to be linked as well.

When not using DUB to manage your project, first use DUB to compile the BindBC libraries with the dynamicBC or staticBC configuration, then pass -betterC to the compiler when building your project.