Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Purpose

The LM-X Python wrapper is a thin Python interface over the native LM-X client library. It provides Pythonic access to the whole entire LM-X API.

Package Contents

 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.

Anchor
prereq
prereq
Prerequisites

Prerequisites for using the Python wrapper include:

  • Python version greater than or equal to version 3Python >= 3.8
  • LM-X SDK build output for your target platform
  • Matching Python bitness and SDK target bitness (32-bit vs or 64-bit)

Building the wheel

Build the Wheel

Recommended (from SDK root)

Building the Python wheel is described below.

Build from SDK root (recommended method)

To build the wheel from the SDK root (recommended), build Build the SDK as usual; . The wheel build is part of the SDK makefile flow:

  • Unix-likeFor Unix/Linux/macOS:
    make
    
  • For Windows (Visual Studio + and nmake environment):
    nmake
    

This runs python/build_sdk_wheel.py and produces:

  • python/lmx-*.whl
  • python/wheel_build.log

Build only the wheel target

To build only the wheel target:

  • Unix-likeFor Unix/Linux/macOS:
    make build_python_wheel
    
  • For Windows:
    nmake build_python_wheel
    

...

Build using manual script invocation

From To build the wheel manually from SDK root, run the following script:

Code Block
python3 python/build_sdk_wheel.py \
  --platform linux_x64 \
  --library linux_x64/liblmx.so \
  --output-dir python \
  --venv python/.venv_wheel

...

 Notes:

Note
  • --platform must match the LM-X host directory

...

  • name (for example linux_x64, win64_x64, darwin_universal).

...

...

  • code 0)

...

  • and

...

  • the SKIPPED: reason

...

  • will be logged in python/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.

Code Block
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 (and run_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. 

Code Block
languagepy
firstline1
linenumberstrue
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:

  1. LmxClient is a thread-safe OO facade over LM-X C APIs.
  2. The wrapper loads native LM-X symbols through ctypes.CDLL (lmx/_ffi.py).
  3. Method calls map 1:1 to native exports (LMX_Init, LMX_Checkout, LMX_Checkin, etc.).
  4. Complex C structs are converted into Python dictionaries/dataclasses by marshal helpers (lmx/_marshal.py).
  5. Python callback options are converted to C function pointers.
  6. Status codes are returned as integers compatible with LMX_STATUS enum values.

Native

...

library resolution order

When creating LmxClient() without explicit library_path, the  the wrapper searches in this order:

  1. Explicit constructor path (library_path) - , where the path must be absolute.
  2. LMX_PYTHON_LIBRARY_PATH env var (absolute file path or absolute directory).
  3. Directory containing lmx/_ffi.py (typically wheel package location).
  4. Current working directory.
  5. OS PATH entries.

If no valid library is found, an LmxUsageError exception is raised with for the attempted paths.

Troubleshooting

Troubleshooting for issues using the Python wrapper are described below.

Wheel not generated

SymptomsIf the wheel is not generated, you will get the following error after the build:

No python/lmx-*.whl

...

To resolve this issue, try the followingChecks:

  1. Inspect python/wheel_build.log for SKIPPED: messages.
  2. Verify that the Python interpreter exists and is callable.
  3. Verify that the interpreter bitness matches target platform bitness.
  4. Verify that the native library path provided to build the script exists.

...

Inability to locate the LM-X client library

Symptoms:

...

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:

  1. Ensure that the

Checks:

  1. Ensure wheel was installed successfully (pip show lmx).
  2. If overriding the library location, set absolute an absolute LMX_PYTHON_LIBRARY_PATH.
  3. If using LmxClient(library_path=...), pass an absolute file path.
  4. Confirm that the file name matches the platform (.so, .dylib, .dll).

Callback-related crashes or unexpected behavior

ChecksIf you are experiencing callback-related crashes or other unexpected behavior, try the following:

  1. Register callbacks via using only set_option() only.
  2. Keep Ensure callback signatures are compatible with expected LM-X callback shapes.
  3. Do not bypass LmxClient internals for callback pointer handling.