The LM-X Python wrapper is a thin Python interface over the native LM-X client library. It provides Pythonic access to the entire LM-X API. Example Python code (local, network, callbacks, licstat, clientstore, trial, admin) is included in the LM-X examples subdirectory.
Usage of the Python wrapper is detailed below.
Package contents
The Python wrapper package is delivered as an LM-X wheel (lmx-*-py3-none-any.whl) that you can install with pip. The wheel contains:
- Python package:
lmx(client.py,_ffi.py,_marshal.py,_callbacks.py,types.py,errors.py) - Embedded native LM-X client library (platform-specific):
liblmx.so(Linux/Unix)liblmx.dylib(macOS)liblmx.dll(Windows)
The wheel is non-pure (root_is_pure = False) and platform-tagged.
Prerequisites
Prerequisites for using the Python wrapper include:
- Python version greater than or equal to version 3.8
- LM-X SDK build output for your target platform
- Matching Python bitness and SDK target bitness (32-bit or 64-bit)
Building the wheel
Building the Python wheel is described below.
Build from SDK root (recommended method)
To build the wheel from the SDK root (recommended), build the SDK as usual. The wheel build is part of the SDK makefile flow:
- For Unix/Linux/macOS:
make - For Windows (Visual Studio and nmake environment):
nmake
This runs python/build_sdk_wheel.py and produces:
python/lmx-*.whlpython/wheel_build.log
Build only the wheel target
To build only the wheel target:
- For Unix/Linux/macOS:
make build_python_wheel - For Windows:
nmake build_python_wheel
Build using manual script invocation
To build the wheel manually from SDK root, run the following script:
python3 python/build_sdk_wheel.py \ --platform linux_x64 \ --library linux_x64/liblmx.so \ --output-dir python \ --venv python/.venv_wheel
--platformmust match the LM-X host directory name (for examplelinux_x64,win64_x64,darwin_universal).- If prerequisites are not met, the build will be skipped (exit code
0) and theSKIPPED:reason will be logged inpython/wheel_build.log.
Installing and starting the wheel
Installing and starting the wheel is described below.
Install the generated wheel
From SDK examples/python, run:
pip install ../../python/lmx-*.whl
Run example scripts
You can start the wheel using one of the following example scripts.
python3 local.py python3 network.py python3 callbacks.py python3 licstat.py python3 clientstore.py python3 trial.py python3 admin.py
You can also use the provided example makefile targets:
- For Unix/Linux/macOS:
make run_local(andrun_network,run_callbacks,run_licstat,run_clientstore,run_trial,run_admin,run_all) - For Windows:
nmake run_local(same target set)
Python wrapper usage example
The following is a simple example of using the Python wrapper.
from lmx import LMX_STATUS, LmxClient, LmxSettings
FEATURE = "f2"
with LmxClient() as client:
status = client.init()
if status != int(LMX_STATUS.LMX_SUCCESS):
raise RuntimeError(f"LMX_Init failed: {status}")
# Setup license path
client.set_option(LmxSettings.LMX_OPT_LICENSE_PATH, "6200@localhost")
# Checkout one license
status = client.checkout(FEATURE, 1, 0, 1)
if status != int(LMX_STATUS.LMX_SUCCESS):
error = client.get_error_message()
raise RuntimeError(f"LMX_Checkout failed: status={status}, error={error}")
# Checkin the license
status = client.checkin(FEATURE, 1)
if status != int(LMX_STATUS.LMX_SUCCESS):
raise RuntimeError(f"LMX_Checkin failed: {client.get_error_message()}")
How the Python wrapper works
The Python wrapper works as follows:
LmxClientis a thread-safe OO facade over LM-X C APIs.- The wrapper loads native LM-X symbols through
ctypes.CDLL(lmx/_ffi.py). - Method calls map 1:1 to native exports (
LMX_Init,LMX_Checkout,LMX_Checkin, etc.). - Complex C structs are converted into Python dictionaries/dataclasses by marshal helpers (
lmx/_marshal.py). - Python callback options are converted to C function pointers.
- Status codes are returned as integers compatible with
LMX_STATUSenum values.
Native library resolution order
When creating LmxClient() the wrapper searches in this order:
- Explicit constructor path (
library_path), where the path must be absolute. LMX_PYTHON_LIBRARY_PATHenv var (absolute file path or absolute directory).- Directory containing
lmx/_ffi.py(typically wheel package location). - Current working directory.
- OS
PATHentries.
If no valid library is found, an LmxUsageError exception is raised for the attempted paths.
Troubleshooting
Troubleshooting for issues using the Python wrapper are described below.
Wheel not generated
If the wheel is not generated, you will get the following error after the build:
No python/lmx-*.whl
To resolve this issue, try the following:
- Inspect
python/wheel_build.logforSKIPPED:messages. - Verify that the Python interpreter exists and is callable.
- Verify that the interpreter bitness matches target platform bitness.
- Verify that the native library path provided to build the script exists.
Inability to locate the LM-X client library
If the import/initialization fails because the LM-X client library path cannot be resolved, you will see the following error:
Could not locate LM-X client library
To resolve this issue, try the following:
- Ensure that the wheel was installed successfully (
pip show lmx). - If overriding the library location, set an absolute
LMX_PYTHON_LIBRARY_PATH. - If using
LmxClient(library_path=...), pass an absolute file path. - Confirm that the file name matches the platform (
.so,.dylib,.dll).
Callback-related crashes or unexpected behavior
If you are experiencing callback-related crashes or other unexpected behavior, try the following:
- Register callbacks using only
set_option(). - Ensure callback signatures are compatible with expected LM-X callback shapes.
- Do not bypass
LmxClientinternals for callback pointer handling.