Skip to content

Provide better error info on dll mismatch - #38

Merged
birkholz-cubert merged 5 commits into
developfrom
feature/provide_better_error_info_on_dll_mismatch
Aug 19, 2026
Merged

Provide better error info on dll mismatch#38
birkholz-cubert merged 5 commits into
developfrom
feature/provide_better_error_info_on_dll_mismatch

Conversation

@birkholz-cubert

@birkholz-cubert birkholz-cubert commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Makes an outdated or mismatched cuvis library visible instead of fatal. Needs cuvis.swig#14 (merged), hence the submodule bump.

  • Import no longer dies on a missing symbol. cuvis.dll is delay loaded on Windows, lazily bound on Linux, so a library that lacks a function only fails at the call.
  • Missing functions are found up front by reading the compiled extension's own import table (PE) or undefined symbols (ELF). No list of function names exists anywhere; it comes from the binary.
  • Each missing function is replaced by a stub that raises RuntimeError naming it, rather than aborting the process. cuvis_il.missing_symbols names them all.
  • The cuvis library is opened by absolute path from $CUVIS before anything binds, so the Windows delay-load helper cannot pick up a stray cuvis.dll from the current directory.
  • Reports both sides of the comparison in the same form, so a mismatch is one glance:
    built against : CUBERT SDK v. 3.5.3 build: 0f416fb6...
    loaded library: CUBERT SDK v. 3.4.1 build: d20de35f...
    
    Two libraries can share a version and still be different builds, so the build hash is what actually separates them. A difference is information, not an error, and is never warned about.
  • Binary introspection lives in its own module (cuvis_il/_imports.py), leaving __init__.py a readable top-to-bottom narrative.
  • CI asserts the build info survived, so a build that loses the version define fails there instead of shipping an "unknown".

Verified

  • Windows and Linux (3.5.3 and 3.4.1 docker images) derive identical 208-symbol sets from two independent binary formats.
  • 3.5.3 binding on a 3.4.1 library: exactly the 3 cuvis_acq_cont_dead_pixel_correction_* functions reported, shadowed, and raising.
  • Degrades cleanly when the build info is absent: a real pre-feature cuvis_il wheel, an extension compiled without the define, and a library banner with no build hash all report "unknown" rather than failing.
  • cuvis.python suite: 90 passed on both platforms.

Known gap

LD_BIND_NOW=1 (or musl) defeats lazy binding and restores the old ImportError: undefined symbol.

The extension and the cuvis library are in sync when built, but the library
installed on a user's machine can be older and simply not export functions the
extension imports. That made `import cuvis_il` fail with an opaque loader error
and took down every consumer, including ones that never needed the missing part.

The module is now delay-loaded on Windows and lazily bound on Linux, so the load
survives. At import the loader reads which cuvis functions the built module needs
out of its own PE import table or ELF .dynsym, probes each against the library it
loaded, and replaces whatever is absent with a stub that raises RuntimeError
naming the symbol. `cuvis_il.missing_symbols` reports them, so a consumer can
decide which of its features are affected, and `built_against_version` says which
SDK the binding expects.

No list of function names is maintained anywhere; the needed set comes from the
binary. Verified on Linux by building against the 3.5.3 SDK image and running
against 3.4.1, which correctly reported the three dead-pixel-correction functions
added since.
The version the binding was compiled against was published through the Python C
API, so it existed only for the Python target and needed a not-CSharp guard. It
is now an ordinary wrapped function, cuvis_built_against_version(), which every
SWIG target language gets for free; verified by building the C# binding from the
same interface. The macro is named CUVIS_BINDING_BUILT_VERSION accordingly.

The delay-load guard now distinguishes a library that cannot be loaded at all
(missing, or its own dependencies such as the CUDA runtime cannot be found) from
one that loads but lacks the function, which previously shared one message.

cuvis_il.library_path names the library the probe actually opened, so a consumer
can report which file it is talking about.
@birkholz-cubert
birkholz-cubert merged commit de779e0 into develop Aug 19, 2026
31 checks passed
@birkholz-cubert
birkholz-cubert deleted the feature/provide_better_error_info_on_dll_mismatch branch August 19, 2026 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant