Skip to content

Software License Dongle for C and C++

C and C++ get the core library itself rather than a binding. Every other language on this site is a thin layer over the same licdongle.h ABI, so you are working with the tested primary implementation, not a translation of it.

Linking

The SDK repository is a CMake package. Fetch it by tag and link the target; the prebuilt library for your platform comes with it, and keynub_copy_runtime places it next to your executable. The library is C99 with hidden symbol visibility and explicit exports, so it drops into an existing build without polluting your namespace.

CMake package version badge

include(FetchContent)
FetchContent_Declare(keynub_licdongle
    GIT_REPOSITORY https://github.com/AB-KeyNub/KeyNub-SDK.git
    GIT_TAG        v1.1.1)
FetchContent_MakeAvailable(keynub_licdongle)

target_link_libraries(myapp PRIVATE keynub::licdongle)      # C; keynub::licdongle_cpp for the C++ wrapper
keynub_copy_runtime(myapp)Code language: CMake (cmake)

For a Visual Studio project without CMake, the same headers and libraries come as a NuGet package: referencing it adds the include path, links the library for the project’s platform (x64, x86 or ARM64) and copies it next to the executable.

For Conan, the repository carries a recipe index: add packaging/conan from a clone as a local-recipes-index remote and require keynub_licdongle/1.1.1; the recipe packages the prebuilt library for your operating system and architecture and exposes the same keynub:: targets through CMakeDeps.

NuGet version badge

Install-Package KeyNub.LicenseDongle.NativeCode language: Bash (bash)
#include <licdongle.h>

licd_ctx *ctx = NULL;
licd_device *dev = NULL;
if (licd_init(&ctx) != LICD_OK) return 1;
if (licd_open(ctx, NULL, &dev) != LICD_OK) return 1;   /* first dongle */

licd_genuine_result g;
if (licd_verify_genuine(dev, &g) != LICD_OK) return 1;
licd_session_open(dev);

unsigned char buf[256];
uint32_t len = 0, total = 0;
licd_record_read(dev, "license", 0, buf, sizeof buf, &len, &total, NULL, NULL);

licd_session_close(dev);
licd_close(dev);
licd_free(ctx);Code language: Arduino (arduino)

Two-call buffer convention

Anything that returns variable-length data follows one rule: call it with a capacity of zero to learn the size it needs, then call it again with a buffer. A zero-length record is a success with a length of zero, not an error — worth knowing before you write the error handling.

C++

The SDK ships an RAII wrapper: construction opens, destruction closes, errors become exceptions if you want them to. Nothing in it is required — it is a header over the same C API, so mixing the two is fine.

Where to put the check

Native code is the hardest target on this site, but a single if (genuine) is still a single conditional jump, and the people who do this for a living find those quickly. Use licd_app_decrypt on data your program genuinely needs, so that patching the check produces a program with nothing to compute rather than a working unlicensed copy.

Code

Runnable sample: c/verify_and_read, cpp/verify_and_read, flat/verify_and_read.c. Binding source: bindings/cpp. Both are Apache-2.0, in the public SDK repository; the prebuilt native libraries are in the repository’s natives/ folder, one per platform.

All supported languages · All industries · Buy a KeyNub · Ask us something