Installation
C#
Install via NuGet:
dotnet add package rfIDEAS.ReaderIntegrationKit
Or via Package Manager Console:
Install-Package rfIDEAS.ReaderIntegrationKit
Requirements: .NET 8.0 or later (the package targets .NET 8.0 and .NET 10.0) on a supported runtime identifier (Windows x64, Linux x64, Linux ARM64, Linux ARMhf, macOS x64, or macOS ARM64)
The NuGet package includes native libraries for Windows x64, Linux x64, Linux ARM64, Linux ARMhf, and macOS (Intel + Apple Silicon, Monterey 12+). They are automatically placed in the correct runtime directory at build time.
Minimal Project
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifiers>win-x64;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="rfIDEAS.ReaderIntegrationKit" Version="*" />
</ItemGroup>
</Project>
Linux ARM64 includes two optimized variants: Raspberry Pi 5 and generic ARM64. At runtime the package selects the variant using the RIK_ARM_VARIANT environment variable when set (pi5 or generic); otherwise it inspects /proc/device-tree/model and falls back to generic. No build-time configuration is required.
The NuGet package includes a universal dylib staged under both runtimes/osx-x64/native/
and runtimes/osx-arm64/native/. An additional copy is present at
runtimes/osx-universal/native/libReaderIntegrationKit.dylib and is used as a fallback
by the runtime loader (NativeLibraryLocator) when a RID-specific path is not found.
Including osx-x64 and osx-arm64 in <RuntimeIdentifiers> is sufficient -- no
osx-universal RID is required in consumer projects.
Python
Install from PyPI with a single command. pip automatically selects the correct platform-tagged wheel for your operating system and CPU architecture:
pip install reader-integration-kit
| Platform / Architecture | Wheel tag |
|---|---|
| Linux x86_64 | manylinux_*_x86_64 |
| Linux ARM64 (generic aarch64 and Raspberry Pi 5) | manylinux_*_aarch64 |
| Linux 32-bit ARM hard-float (ARMhf / armv7) | manylinux_*_armv7l |
| Windows x86_64 | win_amd64 |
| macOS (Intel + Apple Silicon, 12.0+) | macosx_12_0_universal2 |
The wheel bundles the native shared library for your platform. The Python import name is the same on every platform:
import reader_integration_kit
The Linux ARM64 wheel bundles both the Raspberry Pi 5-optimized and the generic ARM64 native library. The correct variant is selected automatically at import time: the package inspects /proc/device-tree/model, and you can override the choice with the RIK_ARM_VARIANT environment variable (pi5 or generic). No package choice is required at install time.
Earlier releases published per-platform packages (for example reader-integration-kit-linux-x86-64). Those names still resolve: they are now thin redirect packages that depend on the unified reader-integration-kit, so existing requirements.txt entries continue to work without changes.
Requirements: Python 3.8+
Verify Installation
from reader_integration_kit.facade import AbstractReader
info = AbstractReader.get_library_info()
print(f"RIK version: {info.get('VersionString')}")
If the import succeeds and prints a version, the native shared library was loaded correctly.
C++
RIK for C++ is distributed as prebuilt libraries with headers for Windows x64, Linux x64, Linux ARM64, Linux ARMhf, and macOS (universal binary covering Intel and Apple Silicon). Two linking variants are available (shared and static). On Linux ARM64, two CPU builds are published:
| Linux ARM target | Prebuilt package |
|---|---|
| Raspberry Pi 5 (optimized) | ARM64 package labeled for Raspberry Pi 5 |
| Generic ARM64 (aarch64) | ARM64 package labeled for generic / non–Pi 5 boards |
| 32-bit ARM hard-float (ARMhf) | ARMhf package |
Download the shared or static archive whose platform name matches your target from the
rf IDEAS download portal. Package names follow the
pattern ReaderIntegrationKit-<version>-<platform>-shared.zip (or -static.zip). On
macOS, the platform token is Darwin-AppleClang-universal and a single archive covers
both Intel and Apple Silicon (universal binary).
For each platform, two linking variants are available:
| Variant | File | Best for |
|---|---|---|
| Shared (default) | .dll / .so / .dylib | Most projects. Smaller executable, simpler updates. |
| Static | .lib / .a | Self-contained deployment with no runtime dependencies on the RIK library file. |
Both variants ship the same headers. The CMake find_package integration works identically for both -- your CMakeLists.txt does not need to change. Just point CMAKE_PREFIX_PATH at whichever package you extracted.
Shared vs Static: Which Should I Use?
Use the shared library if you are building a desktop application, service, or
prototype. It is the simplest path -- your executable stays small, and you can update
the RIK library independently by swapping the .dll, .so, or .dylib file. This is
the recommended default.
Use the static library if you need a single self-contained binary with no external
library files. This is common for embedded deployments, appliance software, or
environments where distributing a separate .dll, .so, or .dylib is inconvenient.
The static library is a "fat archive" that bundles all internal dependencies (protocol,
transport, and third-party libraries) into one file, so you only need the .lib/.a
and the headers. On macOS, the static library requires linking system frameworks
IOKit, CoreFoundation, and AppKit (the CMake find_package integration handles this
automatically).
On Windows, the static library is built with the MSVC static Release runtime (/MT). This means your project must also build in Release mode when linking the static library. Debug builds (/MDd) will fail with LNK2038 runtime library mismatch errors.
If you need Debug builds during development, use the shared library instead -- it works in both Debug and Release because the DLL has its own runtime internally.
This is a standard MSVC constraint that applies to all static C++ libraries, not specific to RIK.
On Linux, the static library works in both Debug and Release builds. There is no CRT mismatch issue. The fat archive includes all dependencies, but your final executable must still link the system libraries pthread and udev. The CMake package config handles this automatically when you use find_package.
On macOS, the static archive works in both Debug and Release builds. The fat archive
includes all internal RIK dependencies. Your final executable must link the system
frameworks IOKit, CoreFoundation, and AppKit. The CMake find_package config
handles this automatically. If using a Makefile, add:
LDFLAGS += -framework IOKit -framework CoreFoundation -framework AppKit
Package Layout
Shared package:
ReaderIntegrationKit-<version>-<platform>-shared/
├── include/ # Header files
├── lib/ # Import library (.lib on Windows), .so symlinks (Linux),
│ # .dylib (macOS), CMake config
├── bin/ # Shared library (.dll on Windows; not present on Linux or macOS)
├── examples/ # Example projects
└── rfIDEAS_EULA.txt
On Linux and macOS, the shared library (.so / .dylib) is in lib/, not bin/.
Static package:
ReaderIntegrationKit-<version>-<platform>-static/
├── include/ # Header files (same as shared)
├── lib/ # Static archive (.lib / .a) and CMake config
├── examples/ # Example projects
└── rfIDEAS_EULA.txt
Option 1: CMake with find_package (Recommended)
Extract the RIK release archive, then configure CMake to find it. This works for both shared and static packages.
cmake_minimum_required(VERSION 3.25)
project(MyApp)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Point CMake to the RIK package
find_package(ReaderIntegrationKit REQUIRED
HINTS ${CMAKE_SOURCE_DIR}/lib/cmake/ReaderIntegrationKit)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE ReaderIntegrationKit::ReaderIntegrationKit)
Configure and build:
cmake -B build -DCMAKE_PREFIX_PATH=/path/to/rik-release -DCMAKE_BUILD_TYPE=Release
cmake --build build
You can pass CMAKE_PREFIX_PATH on the command line (as shown above) or use HINTS in find_package. Either approach works. CMAKE_PREFIX_PATH is more flexible when you want to keep your CMakeLists.txt portable.
Shared library on Windows -- copy the DLL:
When using the shared library on Windows, the DLL must be next to your executable at runtime. Add a post-build copy step:
add_custom_command(TARGET my_app POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_SOURCE_DIR}/bin/ReaderIntegrationKit.dll"
$<TARGET_FILE_DIR:my_app>)
This step is not needed for the static library (there is no DLL).
Static library on Windows -- match the runtime:
When using the static library on Windows with MSVC, ensure your project uses the static Release runtime:
# Required when linking the RIK static library on Windows
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
Option 2: Zip Package (Manual)
- Download and extract the RIK release zip (shared or static)
- Add include paths and link libraries manually in your build system
- For the shared variant, ensure the
.dll,.so, or.dylibis available at runtime (see platform notes below)
Option 3: Traditional Makefile (Linux and macOS)
This pattern also works on macOS with clang++ and .dylib in place of .so. For
static linking on macOS, add -framework IOKit -framework CoreFoundation -framework AppKit
to LDFLAGS (see the macOS Static Library note below).
With the shared library:
# Paths to the extracted RIK shared package
RIK_DIR := /path/to/rik-release
RIK_INCLUDE := $(RIK_DIR)/include
RIK_LIB := $(RIK_DIR)/lib
CXX := g++
CXXFLAGS := -std=c++17 -I$(RIK_INCLUDE)
LDFLAGS := -L$(RIK_LIB) -lReaderIntegrationKit -Wl,-rpath,$(RIK_LIB)
TARGET := my_app
SRCS := main.cpp
$(TARGET): $(SRCS)
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(TARGET)
make
./my_app
With the static library:
# Paths to the extracted RIK static package
RIK_DIR := /path/to/rik-release-static
RIK_INCLUDE := $(RIK_DIR)/include
RIK_LIB := $(RIK_DIR)/lib
CXX := g++
CXXFLAGS := -std=c++17 -I$(RIK_INCLUDE)
# Link the static archive and required system libraries
LDFLAGS := $(RIK_LIB)/libReaderIntegrationKit.a -lpthread -ludev
TARGET := my_app
SRCS := main.cpp
$(TARGET): $(SRCS)
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(TARGET)
make
./my_app # No LD_LIBRARY_PATH needed -- everything is statically linked
The static archive bundles all internal RIK dependencies. You only need to link pthread and udev as system libraries. The resulting executable has no runtime dependency on any RIK library file.
C++ Headers
Both the shared and static packages include the same set of headers:
| Header | Purpose |
|---|---|
Reader/AbstractReader.h | Base class, instance management, metadata |
Reader/Reader.h | Reader operations |
Reader/Reader_C.h | C-compatible API for FFI |
ErrorHandling/ReaderException.h | Exception type |
Platform Notes
Linux
The RIK native library is built on Ubuntu 24.04 and requires glibc 2.38 or later. This applies to all language bindings (C++, C, C#, Python) since they all load the same native shared library.
Distributions that meet this requirement include:
- Ubuntu 24.04+ (glibc 2.39)
- Fedora 39+ (glibc 2.38)
- Debian 13 (Trixie)+ (glibc 2.38)
Older distributions such as Ubuntu 22.04 (glibc 2.35) and Debian 12 (glibc 2.36) are not supported.
If you see an error like:
GLIBC_2.38 not found (required by libReaderIntegrationKit.so)
your system's glibc is too old. Check your version with ldd --version.
USB readers require udev rules for non-root access. See Supported Readers for setup instructions.
Linux ARM64 packages include two builds: Raspberry Pi 5-optimized and generic ARM64. For C++, download the prebuilt zip that matches your board (see the table above). For Python, the single ARM64 wheel bundles both builds and selects the correct one at runtime using RIK_ARM_VARIANT or device-tree detection. For C#, the NuGet package selects the ARM64 native library using RIK_ARM_VARIANT or device-tree detection (see the C# section above). The udev rules requirement for USB access applies equally on ARM platforms.
- Shared library: The
.sofile must be in the linker's search path at runtime. UseLD_LIBRARY_PATH, an-rpathlink flag, or install it to a standard system library directory. - Static library: No runtime library path is needed. The
pthreadandudevsystem libraries are the only external link dependencies. Installlibudev-dev(Debian/Ubuntu) orsystemd-devel(Fedora/RHEL) if not already present. Note: the static library still links glibc dynamically -- the glibc 2.38+ requirement applies to both variants. - Both Debug and Release builds work with either variant.
Windows
USB drivers typically install automatically. If needed, download drivers from rfideas.com/support.
- Shared library: The
.dllmust be in the same directory as your executable, or on the systemPATH. Works with both Debug and Release builds, and with either/MDor/MTin your project. The RIK DLL statically links its own MSVC runtime, so it does not require the Visual C++ Redistributable on the target machine. - Static library: No DLL is needed. Release mode with
/MTonly -- the static library is built with the MSVC static Release runtime (/MT), so your project must also use/MTin Release mode. Debug builds or/MDbuilds will fail withLNK2038runtime library mismatch errors. If you need Debug builds or/MDduring development, use the shared library instead.
macOS
- Minimum version: macOS 12.0 (Monterey) and later, Intel (x86_64) and Apple Silicon (arm64).
- Universal binary: The C++ package (
Darwin-AppleClang-universal) ships a single universal binary. There are no separate Intel and Apple Silicon download archives. - Shared library:
libReaderIntegrationKit.dylibis located inlib/. At runtime, ensure the dylib is findable viaDYLD_LIBRARY_PATH, an-rpathlink flag, or by installing it to a standard library directory (e.g.,/usr/local/lib). - Static library: No runtime library path configuration is needed. Link the system
frameworks IOKit, CoreFoundation, and AppKit (CMake
find_packagehandles this automatically). - USB HID readers: Accessed via IOKit/HIDAPI. No extra drivers are required for standard HID-class readers (and no Linux-style udev rules apply on macOS).
- Permissions: No root /
sudoand no App Sandbox HID/USB entitlements are required for CLI or non-sandboxed apps. Discovery does not require Input Monitoring; opening a keyboard-class HID collection may. See macOS USB Permissions for details, including keystroking behavior, Input Monitoring, and App Sandbox guidance. - Serial readers: Use standard macOS device nodes. Prefer
/dev/cu.*for programmatic use (e.g.,/dev/cu.usbserial-1410);/dev/tty.usbserial-*nodes are also accepted.
Gatekeeper
If macOS Gatekeeper blocks a downloaded .dylib, allow it in
System Settings > Privacy & Security, or clear the quarantine attribute with:
xattr -d com.apple.quarantine libReaderIntegrationKit.dylib
This applies to unsigned local builds and downloaded binaries that have not been notarized.