Skip to content

Add Python SWIG bindings (#ifdef SWIGPYTHON)#101

Merged
lauris71 merged 2 commits intoopen-eid:masterfrom
namespace-ee:feature/python-swig-bindings
Feb 17, 2026
Merged

Add Python SWIG bindings (#ifdef SWIGPYTHON)#101
lauris71 merged 2 commits intoopen-eid:masterfrom
namespace-ee:feature/python-swig-bindings

Conversation

@lnagel
Copy link
Contributor

@lnagel lnagel commented Feb 17, 2026

Summary

Add Python-specific SWIG typemaps and template instantiations to libcdoc.i, guarded by #ifdef SWIGPYTHON. This follows the same pattern as the existing #ifdef SWIGJAVA block and enables Python bindings (e.g. pycdoc) to consume libcdoc.i directly without patching.

What's included

  • %include <exception.i> / %include <stdint.i>exception.i provides SWIG_exception; stdint.i is required for SWIG to properly resolve uint8_t and size_type inside template instantiations (without it, ByteVector.size() returns an opaque pointer instead of an integer)
  • Director typemaps for result_t — enables Python subclasses of DataSource, CryptoBackend, etc. to return result_t values correctly
  • Multi-argument typemaps for (const uint8_t *src, size_t size) and (uint8_t *dst, size_t size) — accepts Python bytes/bytearray for writeData/readData calls
  • std::vector<uint8_t> typemaps — bidirectional conversion between std::vector<uint8_t> and Python bytes, plus output parameter support (std::vector<uint8_t>& appended as second return value)
  • %exception block — translates C++ std::exception to Python RuntimeError
  • Template instantiationsByteVector, ByteVectorVector, StringVector

What's NOT included (already in shared section)

  • %include <std_vector.i>, <std_string.i> (lines 39-40)
  • %apply for integer types (lines 83-88)
  • %feature("director") for all 6 director classes (lines 213-219)
  • %template(LockVector) (line 682)

Test plan

  • swig -python -c++ -directors -I./cdoc libcdoc.i generates correct Python wrappers
  • swig -java -c++ -directors -I./cdoc libcdoc.i produces identical Java output (no regression)
  • pycdoc builds and passes 48/48 tests against this branch without any patches

Add Python-specific typemaps and template instantiations guarded by
#ifdef SWIGPYTHON, following the same pattern as the existing SWIGJAVA
block.

Includes:
- stdint.i for proper uint8_t/size_type resolution in templates
- Director typemaps for result_t (Python int <-> C++ int64_t)
- Multi-argument typemaps for (const uint8_t *src, size_t size) and
  (uint8_t *dst, size_t size) accepting Python bytes/bytearray
- Bidirectional std::vector<uint8_t> <-> Python bytes conversion
- Output parameter typemap for std::vector<uint8_t>& (appended return)
- C++ exception -> Python RuntimeError translation
- Template instantiations: ByteVector, ByteVectorVector, StringVector

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
lnagel added a commit to namespace-ee/pycdoc that referenced this pull request Feb 17, 2026
Python typemaps and template instantiations are now in libcdoc.i
(#ifdef SWIGPYTHON), eliminating the need for the build-time patch.

- Point submodule to namespace-ee/libcdoc (feature/python-swig-bindings)
- Remove patch mechanism from CMakeLists.txt
- Remove patches/libcdoc-python.patch

Upstream PR: open-eid/libcdoc#101
@lnagel lnagel linked an issue Feb 17, 2026 that may be closed by this pull request
1 task
// Exception handling: C++ exceptions -> Python RuntimeError
%exception {
try {
$action
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there functions where exception is explicitly thrown?
We tried to keep API exception free to simplify binding generation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate that the public API is designed to be exception-free using result_t codes — the noexcept try-catch patterns in Io.h and Crypto.cpp confirm that intent.

The %exception block is a defensive safety net rather than a primary error path. Without it, if any C++ exception escapes to Python it would call std::terminate() and abort the entire Python process. With the block, it becomes a catchable RuntimeError instead.

Cases where exceptions could still propagate despite the exception-free API design:

  • std::bad_alloc from any std::vector, std::string, or std::make_unique allocation
  • Vendored library exceptions — jwt-cpp (ecdsa_exception, rsa_exception, token_verification_exception, etc.), picojson (std::runtime_error, std::bad_cast), and httplib during key server communication
  • Base64 decoding in json/base.h throws std::runtime_error on invalid input

It has zero runtime cost in the normal (no-exception) path — just a try/catch frame. Happy to remove it if you prefer to keep the SWIG interface minimal, but it's standard practice for Python bindings as a crash-prevention measure.

@lnagel lnagel marked this pull request as ready for review February 17, 2026 09:19
lnagel added a commit to namespace-ee/pycdoc that referenced this pull request Feb 17, 2026
#8)

Python typemaps and template instantiations are now in libcdoc.i
(#ifdef SWIGPYTHON), eliminating the need for the build-time patch.

- Point submodule to namespace-ee/libcdoc (feature/python-swig-bindings)
- Remove patch mechanism from CMakeLists.txt
- Remove patches/libcdoc-python.patch

Upstream PR: open-eid/libcdoc#101
@lauris71 lauris71 merged commit a03401c into open-eid:master Feb 17, 2026
18 checks passed
@lnagel lnagel deleted the feature/python-swig-bindings branch February 17, 2026 12:34
lnagel added a commit to namespace-ee/pycdoc that referenced this pull request Feb 17, 2026
…gs are merged (open-eid/libcdoc#101)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lnagel
Copy link
Contributor Author

lnagel commented Feb 17, 2026

Thanks! This will be promptly released in pycdoc as well (we are currently tracking your master branch)
https://github.com/namespace-ee/pycdoc/releases/tag/v0.1.2

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.

Upstream PR #2: Add Python SWIG typemaps to libcdoc

3 participants

Comments