Add Python SWIG bindings (#ifdef SWIGPYTHON)#101
Conversation
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>
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
| // Exception handling: C++ exceptions -> Python RuntimeError | ||
| %exception { | ||
| try { | ||
| $action |
There was a problem hiding this comment.
Is there functions where exception is explicitly thrown?
We tried to keep API exception free to simplify binding generation
There was a problem hiding this comment.
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.
#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
…gs are merged (open-eid/libcdoc#101) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Thanks! This will be promptly released in pycdoc as well (we are currently tracking your master branch) |
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 SWIGJAVAblock and enables Python bindings (e.g. pycdoc) to consumelibcdoc.idirectly without patching.What's included
%include <exception.i>/%include <stdint.i>—exception.iprovidesSWIG_exception;stdint.iis required for SWIG to properly resolveuint8_tandsize_typeinside template instantiations (without it,ByteVector.size()returns an opaque pointer instead of an integer)result_t— enables Python subclasses ofDataSource,CryptoBackend, etc. to returnresult_tvalues correctly(const uint8_t *src, size_t size)and(uint8_t *dst, size_t size)— accepts Pythonbytes/bytearrayforwriteData/readDatacallsstd::vector<uint8_t>typemaps — bidirectional conversion betweenstd::vector<uint8_t>and Pythonbytes, plus output parameter support (std::vector<uint8_t>&appended as second return value)%exceptionblock — translates C++std::exceptionto PythonRuntimeErrorByteVector,ByteVectorVector,StringVectorWhat's NOT included (already in shared section)
%include <std_vector.i>,<std_string.i>(lines 39-40)%applyfor 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.igenerates correct Python wrappersswig -java -c++ -directors -I./cdoc libcdoc.iproduces identical Java output (no regression)