Below are the changes for the current release. See the CHANGES file for changes in older releases. See the RELEASENOTES file for a summary of changes in each release. Issue # numbers mentioned below can be found on Github. For more details, add the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.5.0 (06 Aug 2026) =========================== 2026-08-04: Nerixyz #3526 Fix the scope of a template argument being added twice when the argument is named through an alias declaration of a template instantiation, for example: namespace space1 { struct Point { int x; }; template struct Holder { using size_type = int; }; } using PointHolder = space1::Holder; using PointSizeHolder = space1::Holder; generated space1::space1::Point in the wrappers, which did not compile. 2026-08-04: wsfulton [Python] #3473 Generated .pyi stub files now use valid bodies for classes without wrapped members and include imports needed by base classes from %import directives. 2026-08-04: wsfulton [Python] #3473 Add the %pythonstubcode and %pythonstubbegin directives for adding Python code to the .pyi stub file generated by the -pyi and -pyifile options. They are the stub file equivalents of %pythoncode and %pythonbegin and do nothing unless a stub file is being generated. For example: %pythonstubcode %{ import collections.abc %} pyabc.i uses this to import collections.abc into the stub file, so that the abstract base classes it adds with %pythonabc resolve for a type checker. 2026-08-03: wsfulton [Python] When using -builtin, internal new_ prefixed entry points for alternate constructors were mistakenly exposed by the low-level C/C++ module. This occurred for constructors explicitly renamed with %rename, constructor template instantiations named with %template, and synthesized default constructors for C structs renamed with %rename. These constructors are now exported only under their public names, without aliases in the generated Python module. *** POTENTIAL INCOMPATIBILITY *** 2026-08-02: wsfulton [Python] #735 Added the -typehints command line option, which turns on PEP 484 type hints for the whole interface, equivalent to using the global feature: %feature("python:annotations", "typing"); The python:annotations feature takes precedence over the option, so it can still be used to override it for individual symbols. A feature value of "0" turns the type hints off again: %feature("python:annotations", "0") no_hints; The SWIGPYTHON_TYPEHINTS preprocessor symbol is defined when using -typehints. 2026-08-02: Nerixyz, wsfulton [Python] #3469 Fix the PEP 484 type hint generated for a function with more than one output value. Such a function returns the values in a Python list, but was annotated with a bare comma separated list of the individual types, which is not a valid annotation. For example: void divide(int numerator, int denominator, int *OUTPUT, int *OUTPUT); was annotated "typing.Any, typing.Any" and is now "typing.List[typing.Union[typing.Any, typing.Any]]". The function's own return value, when not void, is the first element of the list and is now included in the annotation. Multi-argument argout typemaps now use their matching pytyping typemap too. The C/C++ annotations, that is %feature("python:annotations", "c"), are unchanged. 2026-08-01: wsfulton [D] Fix a director method taking a pointer to a primitive type by const reference, such as: %feature("director") Callback; struct Callback { virtual void callback(int *const ¶m1) = 0; }; The generated D did not compile. The proxy method takes the wrapper class, SWIGTYPE_p_int in this case, but the director callback passed the raw pointer straight to it. 2026-08-01: wsfulton [Python] Fix reference count leak for a swig::SwigVar_PyObject director method argument passed by value. The count was incremented twice on each upcall, once by the assignment into the director wrapper variable and once by the directorin typemap, but only decremented once. 2026-08-01: wsfulton [Python, Ruby, Perl, Octave] Fix director method arguments taking a const reference to the language object type, such as: %feature("director") Callback; struct Callback { virtual void callback(PyObject *const ¶m1) = 0; }; There was no directorin typemap for these, so the argument was wrapped as an opaque proxy object instead of being passed through unchanged. For Ruby the generated code did not even compile. swig::SwigPtr_PyObject const& and swig::SwigVar_PyObject const& are fixed too. 2026-08-01: jschueller, wsfulton [Python] #2015 Fix reference count underflow for a PyObject * director method argument, such as: %feature("director") Callback; struct Callback { virtual void callback(PyObject *param1) = 0; }; The count dropped by one on each upcall until the object was freed while still in use. swig::SwigPtr_PyObject and swig::SwigVar_PyObject too. 2026-07-31: wsfulton [OCaml] Fix wrapping of char array members and parameters, such as: struct S { char name[8]; }; The generated code copied the string with strcpy through the uninitialised local for the array, that is, a null pointer. The string is now just pointed at and the existing bounded copy in the memberin typemap puts it into the array. 2026-07-31: wsfulton [JavaScript] The v8 and node engines now build against v8 13.x and 14.x, as used by Node.js 24 and 26. These removed FunctionCallbackInfo::Holder(), PropertyCallbackInfo::Holder(), String::Utf8Length, String::WriteUtf8 and the untagged v8::Object aligned internal field pointer accessors, and deprecated the untagged v8::External accessors. The minimum supported v8 version is unchanged at 7.4. 2026-07-30: erezgeva, wsfulton [JavaScript, Octave, Perl, Python, R, Ruby, Scilab] #3522 SWIG_FromCharPtrAndSize, SWIG_FromBinaryCharPtrAndSize, SWIG_ToUint8Array, SWIG_FromUint8Array and the Scilab SWIG_AsVal_* and SWIG_From_* macros are now passed on to the generated wrapper instead of being consumed by the SWIG preprocessor. Code that SWIG does not macro expand can now use them, such as a typemap delimited with %{ ... %}: %typemap(out,fragment="SWIG_FromCharPtrAndSize") struct CharBuf %{ $result = SWIG_FromCharPtrAndSize($1.str, $1.len); %} Note that a %{ ... %} block inserting code into the header section is emitted before the fragment defining these macros and so still cannot use them. 2026-07-30: wsfulton [JavaScript] Fixed building the examples and test-suite with the node engine when node-addon-api is not installed. Also, the node-addon-api headers provided by a distro package (such as the Debian/Ubuntu node-addon-api package) are now detected by configure without npm needing to be installed, enabling the napi engine. 2026-07-28: Nerixyz, wsfulton [Python] #3473 Added the -pyi command line option, which generates a .pyi PEP 484 stub file alongside the wrapped module. This gives the python:annotations PEP 484 typing support (see #3390 below) somewhere to attach to when using -builtin or -fastproxy, where the generated module has no (or only a partial) Python-level function/class definitions of its own. The -pyifile option additionally overrides the stub's filename (implying -pyi). When -pyi/-pyifile is active, PEP 484 annotations are only generated in the .pyi, not duplicated in the .py file. Note: this is new and still under active development for this release, like the rest of the pytyping annotation support below - the generated stub content may change in subsequent SWIG releases as the feature matures. 2026-07-28: wsfulton A multicharacter constant, such as 'ab', now has type int instead of char, matching the C and C++ standards. For example: #define MULTI 'ab' is now wrapped as an int. Previously it was incorrectly wrapped as a char, which silently truncated the value. 2026-07-27: Nerixyz, wsfulton [Python] #3390 Added the $pytypename special variable for use in 'pytyping' typemaps, analogous to $javaclassname. It expands to the wrapped proxy class name for a type, or to an opaque SWIGTYPE_* type wrapper class (declared only for static type checkers inside an 'if typing.TYPE_CHECKING' block) for types that have no proxy class. The $*pytypename and $&pytypename variants are also available. The default annotations are unchanged; the special variables only take effect in user-defined 'pytyping' typemaps. The 'typing' module is now imported unconditionally in the generated code as SWIG supports Python 3.5 and later. Note: the pytyping annotation support (this feature, and -pyi below) is new and still under active development for this release. The generated annotations and stub content may change in subsequent SWIG releases as the feature matures. 2026-07-27: wsfulton [JavaScript, Octave, Perl, Python, R, Ruby, Scilab, Tcl] The INPUT typemaps no longer generate a redundant delete of the parameter. For example, the code generated for: int func_input(int *INPUT); no longer contains: if (SWIG_IsNewObj(res1)) delete arg1; The delete could never execute, but GCC was unable to determine this and warned about it via -Wfree-nonheap-object when compiling with optimisation and link time optimisation enabled. 2026-07-27: wsfulton [Java] Fix javac dangling-doc-comments warning "documentation comment is not attached to any declaration" in code generated using -doxygen for enums wrapped as simple constants. The comment for the enum itself is now generated as a plain comment, as there is no Java declaration for the enum for javadoc to attach to: // SomeEnum /* * Comment for the enum itself */ /** * Comment for the first item */ public final static int SOME_ITEM_1 = exampleJNI.SOME_ITEM_1_get(); 2026-07-24: jun66j5, wsfulton [Ruby] #3512 Fix segfault when converting a proxy object that hand written code has detached from its C/C++ object using the pre SWIG 4.5 idiom: DATA_PTR(obj) = NULL; SWIG 4.5 stores the wrapped pointer in an internal struct, so this clears the pointer to that struct rather than the wrapped pointer. Such an object is now treated as one whose pointer has been cleared, as it was before SWIG 4.5, instead of crashing. New code should use the SWIG API instead: SWIG_ConvertPtr(obj, NULL, NULL, SWIG_POINTER_CLEAR); 2026-07-23: Nerixyz [Python] #3408 Corrected the PEP 484 annotations generated by the python:annotations feature: const references to primitive types typing.Any -> as the value type std::size_t, std::ptrdiff_t typing.Any -> int std::string, std::wstring str std::complex, complex char *, wchar_t * str -> typing.Optional[str] long double float -> typing.Any The annotations for std::string, std::wstring, std::complex, wchar_t and the C99 _Complex types are now only generated when the library file defining their in and out typemaps is included. 2026-07-22: jschueller [Python] #3315 Fix "metaclass conflict" TypeError raised when importing a module built with -builtin that defines a class deriving from base classes wrapped in different SWIG extension modules. Each module used to create its own SwigPyObjectType metaclass instance, so a class combining bases from two modules had two unrelated metaclasses. The SwigPyObjectType metaclass (and the SwigPyStaticVar type) are now shared across all modules via the runtime data module. This only affected Python 3.12 and later, since heap types were enabled by default in SWIG 4.4.0. 2026-07-16: jschueller #3497 Fixed the SWIG_CastCmpStruct comparator in the generated runtime so that it provides a strict weak ordering. The comparator mixed the type-pointer ordering with the next-field priority, which could make the binary search in SWIG_TypeCheck miss a valid type entry and fail a cast at runtime. Affects scripting languages using SWIG's runtime type table. 2026-07-15: wsfulton [R] %rename of an enum (including an enum class) is now honoured for the generated R enum name. Previously the C++ enum name was always used for the name passed to defineEnumeration, so a renamed enum was registered under its original name while its enum item names used the renamed name. The enum class returned by the generated accessor functions (via enumFromInteger / enumToInteger) now also uses the renamed name, matching the other target languages. 2026-07-14: wsfulton [Go] %rename of an enum (including an enum class) is now honoured for the generated Go type name. Previously the C++ enum name was always used, so a renamed enum produced a Go type with the original name while its enum item constants used the renamed name. A side effect is that a typedef named enum now uses the typedef name for the Go type instead of the enum name used previously, matching the enum item names used by all the other target languages. The previous behaviour can be restored by renaming the typedef back to the enum name, for example: %rename(Foo) FooEnum; typedef enum Foo { FooA, FooB } FooEnum; makes the generated Go type Foo again. This also fixes the Go type name generated for a forward declared enum, which previously incorrectly embedded the mangled "enum" keyword, for example Enum_SS_ForwardEnum1 instead of ForwardEnum1. 2026-07-14: wsfulton [R] %rename of an enum item is now honoured in the generated R code. The enum item name passed to defineEnumeration previously used the original C++ name, so %rename had no effect on the name used with enumToInteger and enumFromInteger even though the underlying wrapper function was renamed. 2026-07-14: jschueller [R] #2984 Fix scoped enums (enum class) that are not declared within a class. The enum name was added twice to the enum item's wrapper function name, resulting in a mismatch with the name used in the generated R code. 2026-07-12: wsfulton [Lua] #3493 Directors now work with Lua 5.1 and LuaJIT, which do not have the Lua 5.2 uservalue functions ('lua_getuservalue'/'lua_setuservalue') used to store the table of Lua method overrides for a director object. The userdata environment functions that uservalues replaced ('lua_getfenv'/'lua_setfenv') are used instead when wrapping for Lua 5.1. 2026-07-12: wsfulton [Lua] #3493 Restore support for Lua 5.1 and LuaJIT (which implements the Lua 5.1 API) for non-director wrapping. Reverts part of #3394 which dropped Lua 5.1 support. 2026-07-11: wsfulton Fixed a protected or private nested class deriving from a class used elsewhere in the wrapped API producing a runtime upcast helper function that referenced the nested class by its inaccessible qualified name in non-member scope, a C++ compile error ('class ... is protected within this context'). No target language ever wraps a non-public nested class, so it is now never registered for this. Affects any target language using SWIG's generic runtime type table (for example Perl, Python, Ruby, Tcl, Lua), most visibly since the "Keep unsupported nested classes as ignored classes, not forward declarations" change. 2026-07-11: wsfulton [Tcl] Add support for Tcl 9. Fix error: implicit declaration of function Tcl_NewSizeIntObj. 2026-07-09: wsfulton [Guile, JavaScript, Lua, OCaml, Octave, Perl, Python, R, Ruby, Scilab, Tcl] Added 'char *&' (a reference to a char pointer) string typemaps to the target languages that were missing them. A 'char *&' function argument, return value or variable - and, via const reference stripping, a 'char *const&' - is now marshalled as a string in every target language rather than as an opaque pointer; previously only C#, D, Go, Java and PHP did so. The common char_strings test now also has a runme for every target language, all exercising the same set of functions, so there is complete char *& typemap coverage and testing across all supported languages. 2026-07-09: wsfulton [Guile] #3290 Fixed 'invalid conversion from const void* to void*' C++ compilation error when wrapping a function taking a 'const char *' argument hidden behind a typedef, such as 'typedef const char *MyString;'. 2026-07-09: wsfulton [Go] Fixed the wrapper generated for a function or variable returning 'char *&' (a reference to a char pointer), which previously returned a corrupted string because the returned pointer was not dereferenced. 2026-07-09: jschueller, olly, wsfulton [Go] #3290 Fixed 'invalid conversion' C++ compilation errors in the generated wrapper when a function takes a 'const char *' argument hidden behind a typedef, such as 'typedef const char *MyString;'. 2026-07-08: vadz #3403 Fixed a crash the doxygen parser triggered by a structural comment such as @name/@{ followed by a blank line with no documentation attached. 2026-07-08: phetdam [R] #3471 Fix corrupted output or a crash when the -package or -dll command line option is passed when generating R wrappers. 2026-07-06: wsfulton [Python] Removed the Python 2 compatibility macros that were kept in the generated code (pyhead.swg) only for user typemaps. A typemap still using any of these must be updated to call the Python 3 C API directly (the Python 3 equivalent is shown in brackets). Python 2 C API macros removed: PyClass_Check (PyObject_IsInstance), PyInt_Check (PyLong_Check), PyInt_AsLong (PyLong_AsLong), PyInt_FromLong (PyLong_FromLong), PyInt_FromSize_t (PyLong_FromSize_t), PyString_Check (PyBytes_Check), PyString_FromString (PyUnicode_FromString), PyString_Format (PyUnicode_Format), PyString_AsString (PyBytes_AsString), PyString_Size (PyBytes_Size), PyString_InternFromString (PyUnicode_InternFromString), Py_TPFLAGS_HAVE_CLASS (Py_TPFLAGS_BASETYPE) and _PyLong_FromSsize_t (PyLong_FromSsize_t). SWIG string helper macros removed: SWIG_Python_str_FromFormat (PyUnicode_FromFormat) and SWIG_Python_str_FromChar (PyUnicode_FromString). *** POTENTIAL INCOMPATIBILITY *** 2026-07-05: jschueller [Python] #2424 Updated the Python identifier warnings to match Python 3. The list of Python keywords and built-in names that SWIG warns about (a wrapped symbol clashing with one is renamed) now tracks Python 3: the Python 3 keywords and built-ins are added, including nonlocal, True, False, None and print and exec (no longer statements), and the Python 2 only names such as apply, buffer, cmp, file, long, unicode and xrange are dropped. 2026-07-05: jschueller, wsfulton [Python] #3201 Python 2 is no longer supported. SWIG now targets Python 3.5 and later only, and the Python 2 code paths have been removed from the generated wrappers and the SWIG library. Macros that only ever affected Python 2 have been removed and now have no effect if defined: - SWIG_PYTHON_2_UNICODE - in Python 2 this let a unicode object be accepted where a char* or std::string was expected; in Python 3 str is already unicode so it is redundant. - SWIG_PYTHON_STRICT_UNICODE_WCHAR - in Python 2 this forced wchar_t* and std::wstring to accept only unicode and reject byte strings; that is already the only behavior in Python 3. SWIG_PYTHON_STRICT_BYTE_CHAR is unchanged and still supported. The deprecated embed.i library, which only ever worked with Python 2, has been removed, along with the python_static example build targets that used it. *** POTENTIAL INCOMPATIBILITY *** 2026-07-05: wsfulton [Octave] Fix Octave detection in configure with newer versions of Octave. Newer Octave changed the format of the 'octave --version' output from "GNU Octave, version X" to "GNU Octave (arch) version X", so configure no longer recognised Octave as working and silently disabled it. Also fix the mkoctfile check, which passed PATH and LD_LIBRARY_PATH to 'env' unquoted and so broke when either contained a directory with a space in it (as can happen with Windows paths under WSL). 2026-06-17: olly #3480 [Octave, Python, Ruby] Improve handling of NULL vs nullptr vs 0 vs 0L. For these target languages, SWIG has previously treated nullptr or NULL as an integer 0 if used in a situation where the type wasn't known to be a pointer. For nullptr this is never helpful, because it has type nullptr_t which does not implicitly convert to 0, so we no longer do this. For NULL it's rather dubious - C and C++ allow NULL to be defined as integer 0, so `int i = NULL` may work and is occassionally seen in real code, but it is semantically wrong. Also GCC and clang define NULL to a magic value and by default will warn about such misuse, so it's likely to be less common than before they did this. So now SWIG only converts NULL to 0 if used in a context where we know the underlying type is an arithmetic type. Using an integer zero (or equivalent value such as 0L) for a NULL pointer is valid, and SWIG will still treat it as a NULL pointer if used in a context where know the type is a pointer. This is now done based on the value of the integer constant so also applies to 0L (previously it was only done if the value was written in the code as literally `0`). 2026-06-17: wsfulton #3481 Fix the C++17 inheriting constructor pack 'using T::T ...;' over a variadic base pack so that the constructor of every base is wrapped. For example: struct XB { XB(int a); }; struct YB { YB(double a); }; template struct A : T... { using T::T ...; }; %template(AXY) A; Previously the last base's constructor (YB(double) here) was silently dropped and a spurious Warning 526 was reported for it. Every base's constructor is now wrapped and no warning is given. 2026-06-17: wsfulton #3480 Fix a syntax error when a using declaration imports an inherited conversion operator, such as 'using Base::operator int;'. The conversion operator is now brought into the derived class like any other inherited member. 2026-06-17: wsfulton #3479 Fix a syntax error when a using declaration combines the 'typename' disambiguator with a C++17 pack expansion to import a member type from each base in a base pack, for example: template struct Collector : Bases... { using typename Bases::value_type ...; }; 2026-06-17: jschueller #2933 Fixed a regression where repeating an identical using declaration for a type, such as two 'using aa::Foo;' lines, caused that type to be referenced by its unqualified name in the generated wrapper code. This typically led to wrapper code that would not compile when the type was used in a template instantiation. 2026-06-16: wsfulton #1042, #1153 Fix the type of an inherited member brought into a derived class with a using declaration when the base class is named through a typedef or C++11 alias of a template instantiation. For example: template struct Owners { T value; }; template class NodeI { public: using links_type = LinksT; Owners owners; }; template class Cluster : public NodeI { public: using NodeIT = NodeI; using NodeIT::owners; }; %template(OwnersInt) Owners; %template(NodeIInt) NodeI; %template(ClusterInt) Cluster; The wrapped 'owners' member now uses the expanded member type, such as Owners::links_type> for Cluster. Previously the template parameter was left unexpanded as Owners, which failed to compile. The same applies to a member function parameter or return type written in terms of the base template parameter (#1153). 2026-06-16: wsfulton #1827 Fix a hang (infinite loop) when a class inherits from a base class named through a redundant self-referential typedef, such as: typedef struct foo foo; struct foo { }; class bar : public foo { }; The base class is now resolved correctly so the derived class inherits from it. 2026-06-15: wsfulton #2659 A base class can now be named from within a derived class without its namespace qualifier, as C++ allows (the base class name is a member of the base, visible from the derived class). For example namespace Space { struct Base { ... }; } struct Derived : Space::Base { typedef Base base_type; // Base, not Space::Base using base_type::method; // no longer Warning 315 Base copy(Base b) { return b; } // 'Base' is Space::Base }; // The base named through the derived class is also Space::Base. Derived::Base make(Derived::Base b) { return b; } The method 'Derived::copy' and the global function 'make' are now wrapped, taking and returning a Space::Base. Previously a using declaration naming the base through such a typedef gave a spurious 'Nothing known about ...' warning (Warning 315) and the member was silently dropped, and a base class named as a type without its namespace qualifier was not recognised (it was unresolved, or treated as a different type from the base named in full). Such a name - unqualified ('Base') or through the derived class ('Derived::Base') - now resolves to the base class' own type, so a Space::Base value can be passed to both 'copy' and 'make' above. 2026-06-14: wsfulton A using declaration that brings a base class member into a derived class through a typedef naming the base, such as struct Derived : Base { typedef Base base_type; using base_type::method; }; now resolves when the base class declares a constructor of its own. Previously this gave a spurious 'Nothing known about ...' warning (Warning 315) and the member was silently dropped. 2026-06-13: larskanis, wsfulton [Ruby] #3465 #3467 Wrapped objects now use Ruby's embedded TypedData storage on Ruby 3.3 and later, so each wrapped object uses one fewer memory allocation. Ruby 3.2 and earlier are unaffected. 2026-06-07: larskanis, jschueller [Ruby] #3170 #3326 #3456 Generated wrappers now use Ruby's TypedData API instead of the deprecated untyped Data API (Data_Wrap_Struct, Data_Get_Struct, DATA_PTR). Ruby 3.4 warns about the untyped Data API by default (an error under -Werror) and Ruby 4.1 removes it entirely. This is not fully backwards compatible: hand written code (typically in a typemap or %extend block) that reached the wrapped C/C++ pointer through the removed Ruby DATA_PTR macro or Data_Get_Struct must be changed to use the SWIG conversion functions, which work with both old and new SWIG. Read the pointer with void *ptr = 0; SWIG_ConvertPtr(self, &ptr, NULL, 0); and detach (clear) it with SWIG_ConvertPtr(self, NULL, NULL, SWIG_POINTER_CLEAR); See Examples/test-suite/ruby_manual_proxy.i for a worked example. *** POTENTIAL INCOMPATIBILITY *** 2026-06-08: wsfulton Names referring to a C++ class nested inside another class now resolve even when the nested class itself is not wrapped (the usual case for all target languages except Java and C#). A using declaration whose scope qualifier reaches the nested class through a typedef, such as 'using Outer::Nested::Me::method;' where 'Me' is a typedef naming the nested class, now resolves instead of giving a spurious 'Nothing known about ...' warning (Warning 315) and silently dropping the member. An out of line nested class definition written inside the enclosing class, such as: struct Outer::Nested { ... }; is likewise now resolved instead of reporting an 'Outer is not defined as a valid scope' error. 2026-06-04: Nerixyz [Python] #3414 Fix PEP 484 type annotations for multi-argument pytyping typemaps. A typemap matching more than one argument, such as %typemap(pytyping) (int argc, char **argv), is now applied to the whole argument group, so the generated annotation uses the type from the typemap instead of only annotating the first argument with its plain C++ type. 2026-06-02: wsfulton #2694 Improve resolution of qualified names whose scope qualifier is reached through a typedef, including a typedef to a template instantiation. A using declaration such as 'using BaseAlias::Me::Integer;', where 'BaseAlias' and 'Me' are typedefs naming a class, previously gave a 'Nothing known about ...' warning (Warning 315). This includes a typedef to a template instantiation whose template name is itself introduced by a using declaration. It now resolves. 2026-06-01: wsfulton [Go] Fix crash (null pointer dereference) on the first call to a director method returning a reference or pointer type, such as int&, const int& or a class pointer. 2026-06-01: jschueller [Go] #3441 Fix director returning reference to local variable in int& and int&& typemaps. 2026-05-31: wsfulton [Ruby] #3385 Fix segmentation fault when using STL containers of swig::GC_VALUE - the type that wraps an arbitrary Ruby object - such as std::vector or a std::map or std::set with a swig::BinaryPredicate comparator proc, while the Ruby 3.x garbage collector compacts the heap (GC.compact or GC.auto_compact). The Ruby objects stored in such containers are now retained correctly across a compaction, instead of occasionally crashing the interpreter. 2026-05-30: erezgeva [Lua] #3394 Drop support for Lua 5.0 and Lua 5.1. Minimum supported Lua version is now 5.2. SWIG no longer compiles wrappers for Lua 5.0 or 5.1 (this includes LuaJIT consumers still using the 5.1 ABI). Removed -squash-bases command-line option (and the SWIG_LUA_SQUASH_BASES runtime path). The implementation was broken; classes now always use the standard base-lookup path. Using this command-line option will generate error swig error : Unrecognized option -squash-bases Removed deprecated -no-old-metatable-bindings command-line option. Old-style metatable bindings are always generated, matching the long-standing default. Using this command-line option will generate error swig error : Unrecognized option -no-old-metatable-bindings *** POTENTIAL INCOMPATIBILITY *** 2026-05-30: wsfulton C++17: parse user-defined deduction guides used for class template argument deduction, for example: template struct Box { Box(T); }; Box(int) -> Box; // non-template deduction guide template Box(T) -> Box; // templated deduction guide A guide is written at the same scope as the class template, either as a non-template declaration or, when itself a template, under a template parameter list. A deduction guide is not a function and emits no symbol - it only steers argument deduction at compile time - so there is nothing to wrap and SWIG parses and ignores it. Previously any deduction guide resulted in a syntax error. 2026-05-28: wsfulton #2951 Inheriting constructors now work when the immediate base class is named through a typedef, including when that base is a template instantiation: struct D : C { typedef C base_type; using base_type::base_type; }; Previously SWIG warned "Nothing known about 'base_type::base_type'" and wrapped only the default constructor, leaving the inherited constructors unavailable from the target language. 2026-05-28: wsfulton #2951 A using-declaration whose qualifier is a type-template parameter used directly as the base class - the mixin idiom - template struct Derived : I { using I::I; using I::call; }; now has its template parameter substituted during instantiation, so wrappers for the inherited members - including inheriting constructors via 'using I::I;' - are emitted on the instantiated derived class. Previously SWIG warned "Nothing known about 'I::call'" and no wrapper was generated. 2026-05-27: wsfulton C++20: parse and support constrained alias templates. Both the type-constraint shorthand and the requires-clause long form are now accepted: template using NumBox = Box; template requires Numeric using ReqBox = Box; The requires-clause form previously resulted in a syntax error. Both forms wrap identically to an unconstrained alias template. Note that the constraint does not affect the generated wrappers. The C++ compiler enforces it when compiling the emitted wrapper. Wrapping continues to use the documented two-step pattern: %template(Name) on the underlying template, followed by an empty %template() for each alias. 2026-05-26: wsfulton [Python] Class docstrings under -builtin now match the non-builtin proxy module. When neither %feature("docstring") nor a doxygen comment is supplied, inspect.getdoc(MyClass) previously returned the qualified C++ name such as "::MyClass"; it now returns "Proxy of C++ MyClass class." (or "Proxy of C MyStruct struct.") when %feature("autodoc") is enabled, and the empty string otherwise. Alternative documentation strings can of course still be set via %feature("python:tp_doc", "...") on the class. *** POTENTIAL INCOMPATIBILITY *** 2026-05-25: wsfulton [Python] %nokwargs on an individual function now correctly opts that function out of keyword argument handling using the -keyword option or a module-wide %feature("kwargs") has enabled kwargs globally. The change is visible under -builtin, where the affected function's wrapper is now generated with METH_VARARGS instead of METH_VARARGS|METH_KEYWORDS, so calling it by keyword raises TypeError as expected. Previously, %nokwargs was silently ignored once -keyword was passed. 2026-05-25: wsfulton, jschueller #3448 Fix ccache-swig (and the bundled CCache test suite) failing cache lookups when used with Apple clang 21 or upstream LLVM clang 21. These compilers now emit clang: warning: argument unused during compilation: '-c' [-Wunused-command-line-argument] when -c and -E are passed together. ccache-swig invoked the preprocessor as "cc -c -E foo.c" and hashed its stderr, so the warning text was folded into the cache key and prevented a cache hit between compiling foo.c and the equivalent preprocessed foo.i. ccache-swig now omits -c when invoking the preprocessor. 2026-05-25: clintonstimpson #3425 Suppress unused function warnings in the generated code when compiling with Clang-CL. 2026-05-24: wsfulton Fixed a one-byte buffer overflow in the cdata.i memmove typemap that occurred when the data length exactly matched the destination buffer size. 2026-05-20: erezgeva [Guile, JavaScript, Python, Scilab, Tcl] #3383 The cdata.i library functions (cdata, memmove and similar) now use a binary data type instead of a string, so that all byte values 0-255 round-trip correctly. The target language type used by the cdata.i functions has changed: - Python: bytes object (was str) - JavaScript: Uint8Array (was string) - Tcl: list of integers (was string) - Scilab: list of uint8 values (was string) In Python, passing a str now fails with: TypeError: in method 'memmove', argument 2 of type 'void const *' so pass a bytes object instead. Guile cdata now also handles all byte values correctly. *** POTENTIAL INCOMPATIBILITY *** 2026-05-19: jmarrec #3415 Fix segmentation fault when a class declares a public 'using Base::method;' that names a base-class member template with no %template instantiations and also declares a protected concrete override of the same name. 2026-05-16: erezgeva [Lua, Octave, Perl, PHP, Python, Ruby, Scilab, Tcl] #3409 Add memory allocation failure protection to the argcargv typemaps and to the string duplication paths in pystrings.swg, perlstrings.swg, rubystrings.swg and rfragments.swg. Potentially incompatible change: the `%new_copy_array` macro has been removed. User interface files calling `%new_copy_array(ptr, size, T)` will be passed through to the C/C++ compiler unchanged and fail with an error such as: error: expected expression before '%' token Replace such calls with an explicit allocate and copy that checks for allocation failure, e.g. T *p = %new_array(size, T); if (p) memcpy(p, ptr, size * sizeof(T)); Potentially incompatible change: the `%typemaps_string` macro in `Lib/typemaps/strings.swg` now takes an additional argument naming a `SWIG_NewCopyCharArray` style fragment, and the related `%typemaps_string_alloc` macro has been removed (its allocator customisation is now expressed by passing the new argument to `%typemaps_string` directly). Existing callers of `%typemaps_string` with the old signature will fail with: Error: Macro '%typemaps_string' expects 13 arguments Existing callers of `%typemaps_string_alloc` will fail with: Error: Unknown directive '%typemaps_string_alloc'. Update such calls to pass the additional fragment, modelled on `SWIG_NewCopyWCharArray` in `Lib/typemaps/wstring.swg`. *** POTENTIAL INCOMPATIBILITY *** 2026-05-16: akarantanapa [C#] #3406 Fix the std_wstring.i and wchar.i pointer initialisations so the generated code compiles as both C and C++. 2026-05-18: wsfulton [Python] Doxygen comments on constructors are now emitted on __init__ when wrapping with -builtin, matching the default (non-builtin) behaviour. Previously inspect.getdoc(Cls.__init__) returned the generic "Initialize self. See help(type(self)) for accurate signature." regardless of the Doxygen documentation on the C++ constructor. 2026-05-15: blowekamp [R] #3407 Fix compilation with R 4.6.0 which removed the non-API macro SET_S4_OBJECT and made CHARACTER_POINTER return a const pointer. Use Rf_asS4, SET_STRING_ELT and STRING_ELT instead. These replacement APIs have been available since R 2.x so no version guards are required. 2026-05-28: wsfulton C++17: parse and support pack expansion in a using-declaration (P0195), e.g. template struct Overloaded : Ts... { using Ts::operator()...; }; The names introduced by the using-declaration depend on an unexpanded template parameter pack, so SWIG accepts the syntax but produces no wrappers until %template instantiates the class. %template now expands the pack using-declaration into one concrete using-declaration per base type, so the instantiated proxy class has a wrapper for each inherited member - matching how an ordinary 'using Base::name;' inside a class template behaves after instantiation. Combined with %rename(call) *::operator(); the proxy of Overloaded has overloaded call(int) and call(double) methods that dispatch to the matching base. 2026-05-14: wsfulton C++17: detect class template argument deduction (CTAD) in a variable declaration, where a variable is declared with a bare class template name and the template arguments are deduced from the initializer, e.g. template struct Box { T value; Box(T v) : value(v) {} }; Box bx{42}; // CTAD deduces Box from the constructor (and, with C++20 P1816, also for aggregates with no deduction guide). CTAD is only valid for variables, so this is the only declaration kind affected. SWIG performs no template argument deduction, so it now issues Warning 347 and skips the variable instead of generating uncompilable wrapper code that names the template without arguments. 2026-05-14: wsfulton User-defined literal operators are now emitted without the space between the "" and the suffix, that is operator""_x rather than operator "" _x. The spaced form is deprecated in C++23 (CWG2521) and is an error under clang and MSVC with -Wdeprecated-literal-operator. 2026-05-14: wsfulton [Perl] Fix a -Wimplicit-const-int-float-conversion compiler warning in the generated code. 2026-05-12: wsfulton C++20: %template can now instantiate abbreviated function templates that mix 'auto' parameters with a variadic explicit template pack, e.g. template std::string f_mix(auto x, Ts... ys); %template(f_mix_isd) f_mix; Per the C++20 standard ([dcl.fct]/19) the invented type template- parameter for each 'auto' parm is appended after the explicit list, so the %template argument list is bound positionally: leading non-variadic parameters first, the variadic pack absorbs the middle args, then one trailing arg per 'auto' in declaration order. Above, Ts={int, std::string} (absorbed by the pack) and the trailing 'double' binds to the invented parm for 'x', giving the effective wrapper signature as: f_mix(double x, int y1, std::string y2) 2026-05-12: wsfulton C++20: parse and support decorated 'auto' parameters in abbreviated function templates: int h(auto& x); // reference int i(auto* x); // pointer int j(auto&& x); // forwarding reference int k(const auto x); // const by value int l(const auto& x); // const reference int m(Numeric auto& x); // constrained reference int n(const Numeric auto& x); // const constrained reference 2026-05-12: wsfulton C++20: fix segmentation fault when mixing abbreviated function template 'auto' parameters with an explicit template parameter list, e.g. template T mix(T x, auto y) { return T(x + y); } %template(mix_id) mix; Each 'auto' parameter introduces an invented type template parameter appended to the explicit template parameter list. When using %template, supply arguments for the explicit parameters first, then one for each 'auto' parameter in declaration order. 2026-05-11: wsfulton C++20: warning 332 (unresolved type-constraint in a templated parameter list) is no longer emitted. The remap to 'typename T' is still applied silently, so wrappers continue to compile when the concept definition is visible only to the C++ compiler. 2026-05-10: wsfulton C++20: template parameters with a type-constraint now accept a template-id concept-id as the constraint, the form most often seen with STL concepts like 'std::convertible_to', 'std::same_as', 'std::derived_from' or 'std::predicate'. Examples: template T> int to_int(T x); template concept Pair = std::convertible_to; template T> int first_int(T x); 2026-05-09: wsfulton C++20: parse abbreviated function templates with a constrained auto return type, including the trailing return form: Numeric auto half(int x) -> int { return x / 2; } Numeric auto cube_constrained(Sized auto x) -> int { return x*x*x; } %template(cube_constrained_int) cube_constrained; When an explicit (non-auto) trailing return type is provided the function wraps normally (the trailing return is the wrapped type); without one, the function is ignored with a warning since SWIG cannot deduce the return type, matching plain 'auto fn(...)' behaviour. As a side fix, plain 'auto fn(Concept auto x) -> Type' now correctly introduces an invented type template parameter for the auto parameter so '%template' instantiates it. 2026-05-09: wsfulton C++20: parse and support type-constraints on template parameters. 'template' is now accepted as the standard shorthand for 'template requires Numeric', as per the C++20 standard. This includes ::-qualified concept-ids, variadic packs, default arguments and class templates. template concept Numeric = std::integral || std::floating_point; template T cube(T x) { return x * x * x; } %template(cube_int) cube; If the type-constraint identifier has not been parsed by SWIG, the parameter is silently remapped to 'typename T'; the generated wrapper compiles when the concept is visible to the C++ compiler. 2026-05-09: wsfulton C++20: parse abbreviated function templates with constrained auto parameters. Each auto parameter with a type-constraint (e.g. 'Numeric auto') introduces an invented type template parameter carrying the type-constraint as a captured constraint. int twice_numeric(Numeric auto x) { return x + x; } %template(twice_numeric_int) twice_numeric; 2026-05-09: wsfulton C++14: parse generic lambdas - lambdas with one or more 'auto' parameters. Like non-templated lambdas, generic lambdas are not wrapped, but they no longer cause a syntax error when SWIG parses a header that contains them. auto twice = [](auto x) { return x + x; }; auto add = [](auto a, auto b) { return a + b; }; 2026-05-09: wsfulton C++20: parse abbreviated function templates - ordinary functions with one or more 'auto' parameters. C++20 treats the function as a function template with invented type template parameters for each auto parameter. Abbreviated function templates can now be wrapped with %template, just like a regular templated function. Note that an explicit (non-auto) return type is required. The return type is not included in the %template instantiation and SWIG remains unable to deduce auto return types. double scale(auto x, auto factor) { return x * factor; } %template(scale_id) scale; 2026-05-09: wsfulton #3413 C++20: accept prefix requires-clauses on templated lambdas, and trailing requires-clauses placed after the lambda's return type. auto prefix = [] requires Numeric (T x) { return x + x; }; 2026-05-07: wsfulton #3413 %template applied to a C++20 concept now reports an error instead of silently producing a malformed wrapper. 2026-05-05: wsfulton #3413 C++20: parse a requires-expression as a primary in expression position, not just inside a requires-clause. This allows a namespace scope variable template to be initialised from a requires-expression. template constexpr bool Addable = requires (T t) { t + t; }; %template(addable_int) Addable; 2026-05-05: wsfulton Document existing coverage for C++14 variable templates which requires a %template instantiation of the variable template, resulting in a read only variable wrapper. template constexpr int bits_in = sizeof(T) * 8; %template(bits_in_char) bits_in; 2026-05-04: wsfulton #3413 Basic support for C++20 concept declarations and requires-clauses on function templates, in both the trailing position and the prefix position (between the template parameter list and the declarator). Both constructs are silently consumed: a concept declaration produces no parse tree node, and a constrained template wraps as if it were unconstrained. template concept Numeric = std::integral || std::floating_point; template T cube(T x) requires Numeric { return x * x * x; } template requires Numeric T quad(T x) { return x * x * x * x; } template concept Summable = requires (T t) { t + t; }; template T sum_pair(T a, T b) requires Summable { return a + b; } Compound constraints containing trailing return type constraints also work: template concept AddableSame = requires(T a, T b) { { a + b } -> std::same_as; }; 2026-05-03: wsfulton [R] Fix function pointer wrappers involving move-only types. 2026-05-02: mmomtchev, wsfulton #341 #3297 #3298 Add support for wrapping std::function via the SWIG library file std_function.i. The partial specialization std::function is wrapped so that a C++ callable (free function, lambda, bound member function or functor) can be returned from C++ to the target language and invoked there. %include %inline %{ std::function MakeFunctor(int pass) { return [pass](int passcode, const std::string &name) -> bool { return passcode == pass && name == "magic"; }; } %} %template(MyFunctor) std::function; One %template instantiation is required per RET(ARGS...) signature. std_function.i renames operator() to call so that target languages which cannot wrap operator() as an identifier still get a usable method name, and ignores the default constructor so std::function instances always originate on the C++ side. See the new section "std::function" in the SWIG library chapter of the documentation for the full pattern, limitations and target-language notes. 2026-05-01: wsfulton Fix partial template specialization where the specialized argument is a function type, including function types carrying a parameter pack. This makes std::function and similar wrappers work correctly, eg: template class function; template class function { ... }; %template(FuncIntInt) function; %template(FuncVoid) function; %template(FuncMixed) function; Previously the primary template was incorrectly chosen for these instantiations. The partial specialization is now matched, with the function return type and parameter list (including trailing parameter packs) bound correctly. Lib/std/std_function.i has been updated to use the standard forward declaration of std::function. 2026-04-26: wsfulton Fix partial template specialization where the specialized argument is a templated type carrying a parameter pack, eg: template struct Pack {}; template struct Foo {}; template struct Foo> {}; %template(FooEmpty) Foo>; %template(FooStr) Foo>; %template(FooMix) Foo>; Such partial specializations are now matched and instantiated correctly for any pack length, including the empty pack. 2026-04-25: wsfulton Advanced %rename fixes for templates. It is now possible to use %rename on instantiated templates for various corner cases, see "Template renaming" section in SWIGPlus.html. For example, it is now possible to selectively rename overloaded templated functions. The full power of %rename (such as using regex) can now be used on templates. Example fix using %rename on templates: namespace Quirky { template void funky() {} } %rename("%s_void") Quirky::funky(); %template(funky_int) Quirky::funky; Will now generate funky_void() where previously there there was no wrapper, just a warning: Warning 503: Can't wrap 'funky< int >_void' unless renamed to a valid identifier. 2026-04-17: jwuttke #3403 Fix -doxygen: @file block bleeding into the first class docstring. Single-line //! (or ///) comments forming a file-level header (starting with @file) are now correctly discarded instead of being concatenated into the next declaration's docstring. 2026-03-26: Nerixyz [Python] #3389 Add missing C annotations and PEP 484 annotations to constants. 2026-03-25: christophe-calmejane [Lua] #3387 Added support for std::shared_ptr and boost::shared_ptr. 2026-03-25: Nerixyz [Python] #3334 Add PEP 484 annotations for a few simple types - primitive types and C strings. 2026-03-23: christophe-calmejane [Lua] #3386 Add support for std::unordered_set and std::unordered_map. 2026-03-23: erezgeva [Go] #3360 Makefile support for using and testing Go on Windows. 2026-03-20: christophe-calmejane [Lua] #3306 Added support for nested classes. 2026-03-19: wsfulton [C#, D] Always initialise the return type in the C/C++ code. Users with custom typemaps may need to provide a valid initial value via the "null" attribute in the "out" typemap if 0 is not a valid initial value. 2026-03-19: erezgeva #3348 Avoid a potential segfault by handling a failed dynamic_cast in generated director code by instead throwing a language specific exception: "'self' is not a director". 2026-03-18: jschueller [JavaScript, Python, Ruby] #3372 Remove redundant semicolons in the generated director and iterator code to fix -Wextra-semi compiler warnings. 2026-03-18: erezgeva [OCaml] #3378 Fix the cdata.i library so the cdata and memmove functions return the raw C data correctly. 2026-03-10: xSetech [Python] #3365 Fix descriptor() type lookup when SwigPyIterator is renamed via #define for use in multiple modules. 2026-03-06: wsfulton [Java] #3354 Fully qualify generated Java interfaces when using the %interface and %nspace features. 2026-03-05: FilipAlg [C#] #3354 Fully qualify generated C# interfaces when using the %interface and %nspace features. 2026-03-05: christophe-calmejane [Lua] #3305 Added std::array and std::set support. 2026-03-04: wsfulton #3312 SWIG source code in Source directory is now formatted with clang-format. Supported versions of clang-format are 18 and later (tested up to and including version 22). Formatting is enforced in Github Actions so contributors to the source code base must use clang-format before raising Github pull requests. Separate formatting only commits are strongly discouraged; each commit should be correctly formatted when committing (or format only commits squashed into prior commits prior to pushing to Github). Please see docs in Doc/Manual/Extending.html. In order to the ease pain of working on git branches that were branched prior to the commit on master that reformatted the code (bbdec1f7), the following is suggested. 1. Merge/rebase onto the prior commit bbdec1f7^ 2. Copy Source/.clang-format from bbdec1f7 into your working directory 3. Run the identical commands specified in the bbdec1f7 commit message The branch should then merge cleanly onto bbdec1f7. 2026-02-28: ArtemKozak666 [C#] #3321 Fix undefined behaviour in std::string_view directorin typemap. 2026-02-27: erezgeva Various improvements to Github Actions CI testing to increase coverage notably with additional Windows and MacOS testing including via CMake. 2026-02-27: phetdam #3191 #3332 Buiding SWIG executable with CMake enhancements. - Update PCRE2 find module to be compatible with upstream CMake config script. - Update docs for users wishing to use CMake to build SWIG. 2026-02-23: aryler #3304 Correct LDSHARED for OpenBSD. 2026-02-20: benzwick [Guile] #3336 Fix segfault in Guile -proxy when class has public member variable. 2026-02-20: benzwick #3337 Fix cross-module type cast lookup in SWIG_InitializeModule using multiple modules. 2026-02-11: degasus, wsfulton #3327 [Java, C#] Add missing Doxygen documentation comments to code using the %interface directives. 2026-02-07: wsfulton #3323 Fix -Wsign-compare warning in 32-bit builds in SWIG_TypeClientData. 2026-02-04: jschueller #3325 Add include guard when generating SWIG runtime header. 2026-01-21: jschueller #3019 Issue deprecation warning if `%typedef` is used. This is an undocumented directive which SWIG has treated as an alias for the standard C/C++ `typedef` since at least 1996. Replace any remaining uses with `typedef`, which also works with older SWIG versions. 2026-01-15: olly [Octave] Octave 6 is now the oldest version we aim to support. We haven't had any automated testing of older Octave versions since GHA dropped support for Ubuntu 20.04 on 2025-04-01. 2026-01-15: jschueller [Octave] Fix save_binary prototype to be correct for Octave >= 6. 2025-12-17: ysmilda [Go] #3291 - Add `-unique-id` and `-no-unique-id` flags to enable/disable the addition of a unique id to the generated function names. - Deprecate `-cgo` flag as this doesn't do anything. - Cleanup docs and help output. 2025-12-12: christophe-calmejane [Lua] #3295 Add director support for Lua. 2025-12-05: jaw [Python] #3287 Fixes for gcc warnings: -Wconversion -Wsign-conversion. 2025-11-08: wsfulton Fix handling of typedef to void in class methods/constructor's parameter lists, such as: typedef void VOID_TYPE; struct S { S(VOID_TYPE); int f(VOID_TYPE) const; }; 2025-11-06: olly [Octave, Ruby] #3281 `FALSE` and `TRUE` are no longer treated as aliases of `false` and `true` when generating documentation comments. 2025-11-06: olly [PHP] Fix -Wunused compiler warnings for unused helper functions in the generated code. 2025-11-04: olly [Octave] Fix a -Wmisleading-indentation compiler warning in the generated code. 2025-11-02: wsfulton [Go] Fix various compilation problems when wrapping rvalues references. 2025-11-01: wsfulton Fix wrapping rvalue reference typedefs in director constructors. 2025-11-01: wsfulton Multiple typedefs involving references fix. If a typedef to a typedef of a reference was wrapped, uncompilable code was generated. Note: this was previously okay with just a single typedef to a reference. Affected wrapping global and member variables as well as parameters in member methods and constructors. 2025-10-27: wsfulton #3276 Add missing std::move when wrapping move constructors for directors. Also add missing std::move for wrapped director (virtual) methods with rvalue references.