c840bb728a886fd8b9a9f241c2d2b603f0e7a91b changed this code to make type casting threadsafe. It's hard to be sure without having a reproducer, but it looks like the problem may still exist as cast->type is still only updated here if (type == swig_module.type_initial[i]).
We're still generating the same code AFAICS. Retesting though I found it does actually work provided you use consistent naming: $ RUBY=ruby3.2 $ echo '%module OpenBabel' > test.i $ swig -ruby test.i $ g++ -shared -fPIC \ -I"`$RUBY -r rbconfig -e 'puts(RbConfig::CONFIG["rubyhdrdir"] || "")'`" \ -I"`$RUBY -r rbconfig -e 'puts(RbConfig::CONFIG["rubyarchhdrdir"] || "")'`" \ -o OpenBabel.so test_wrap.c $ $RUBY -I. -e 'require "OpenBabel"' $ So if you use %module OpenBabel then you need to name the shared...
I've merged fixes for the remaining cases here - should be released in SWIG 4.4.0.
syntax error when parsing complex default values
Moved to https://github.com/swig/swig/issues/3197 in the live tracker
templates using import fails
I'm going to close as a duplicate of the newer ticket in the live tracker, and note there that the testcase here should be checked against any candidate fix.
no warning for multiple %module statements
We also rely on this being accepted in some testcases - e.g. preproc_constants_c.i contains %include "preproc_constants.i" but both contain %module directives. I can see an argument for warning about this, but %module is both conventionally and most naturally put at the very top of the file, so in practice I don't think this situation is going to occur in a way which causes confusion in real world use. Fixing would seem to require adding a warning and adjusting all the uses in the testsuite to either...
C++ memory leak of temporaries on exception
Fix in git by c77498d5db7f661859fdc86eeb277ab6c67f7fbf.
SWIG generates invalid code for 2D array of int*
SWIG generates invalid code for 2D array of function pointers
Reproducible with SWIG 4.3.0. Looking at the manual again, this part does actually seem to suggest that types without names should work: Each type pattern is either a simple type, a simple type and argument name, or a list of types in the case of multi-argument typemaps. @wsfulton Do you think this is a code bug or a documentation bug? I looked at the code and it makes my head spin, but I could fix the docs to clearly say this isn't supported (from my testing the first argument in a multi-argument...
Reproduced with current git master. Interestingly %typemap(default) (int &a, int &) { also works, but %typemap(default) (int &, int &b) { doesn't. I don't see where in the docs it explicitly says that omitting the parameter names should work though. I do see this text (which has been there since before 2002 it seems): Multi-argument typemaps are also more restrictive in the way that they are matched. Currently, the first argument follows the matching rules described in the previous section, but all...
OUTPUT typemap for references in Lua not working
Looking at this again in more detail, I think SWIG's default wrapping is actually reasonable here. In case of OUTPUT the wrapper routine should create the output object and send the dereferenced pointer to the C++ routine. Then the object should be returned by Lua. My filled-in reproducer above could not be automatically wrapped as you suggest because there's no default constructor for MyType so the output object creation would also need to be told how to construct a suitable dummy object. The typemap...
@wsfulton Did your recent nested class change to -xml address this too?
Looking into this, the cause of the leak is actually quite obvious - we have this vtablearray as a member of the object and use it to cache swig::SwigVar_PyObject for each method looked up, which wraps a PyObject but we never free these anywhere. That effectively means we leak a PyObject* for each directed method per object. This isn't quite right - swig::SwigVar_PyObject is effectively a smart pointer to a PyObject which decrements the reference count on destruction. Johan's explanation in the original...
I also realised that the current -dirvtable isn't correct in the face of monkey patching of a method of an object after it has first been called - it'll cache the original version. Caching the Python string name for the object doesn't suffer from this issue. It's arguably a corner case, but it's not nice that it affects the Python semantics of calling a method. (If we did drop the caching of methods, it would also fix https://sourceforge.net/p/swig/bugs/868/)
Hmm, there seems to be a huge range of variation in the timings I get. Maybe I need to repeat using something like Python's timeit module which is designed for microbenchmarking.
If we just cache the return values from SWIG_Python_str_FromChar("foo") which avoids converting the method name to a python string on each call we seem to actually get all the gain the optimisation gives without any measurable overhead in the short-lived object case and without the leak: real 0m2.724s user 0m2.720s sys 0m0.004s (better than 3.795s; within the noise of 2.779s) real 0m2.136s user 0m2.132s sys 0m0.004s (within the noise of 2.184s; better than 3.631s) I think we should replace -dirvtable...
Oh except that can't work in the face of monkey patching, because a method can vary per-object: class A: def __init__(s): pass def t(s): print("A::t") a=A() def new_a_t(): print("new_a_t") a.t = new_a_t a2=A() a.t() a2.t() I did a quick benchmark to see how much this optimisation helps in something like the best case: from leaktest import * class Bar(Foo): def foo(self): return 0.0 b = Bar() for j in range(10000000): c = foo(b) The optimisation does make a clear difference in this case - without...
This looks promising: >>> class A: ... pass ... >>> a=A() >>> t = type(a) >>> t._swig_vtable=(None, None) >>> a2=A() >>> type(a2)._swig_vtable (None, None) If we just store the vtable as an attribute of the type then we only have one instance per Python subclass. Not sure if type objects can be deleted, but if they can then Python should automatically clean this up for us.
Still reproducible with git master shortly before 4.3.0. Looking into this, the cause of the leak is actually quite obvious - we have this vtablearray as a member of the object and use it to cache swig::SwigVar_PyObject for each method looked up, which wraps a PyObject but we never free these anywhere. That effectively means we leak a PyObject* for each directed method per object. We could probably call Py_DECREF() on these in the destructor, but it seems non-ideal that we cache per object as the...
[java] missing unsigned long long array typemaps
Looks like this was addressed in SWIG 4.1.0 so closing - this was the commit: commit 1eebc2335a7d607e3bb7466ce125a9495304c029 Author: Andy Polyakov <appro@cryptogams.org> Date: Sun Jan 24 13:01:36 2021 +0100 Lib/java/arrays_java.i: use actual C/C++ type in JAVA_ARRAYS_TYPEMAPS. long long[] map was using JNI type as C/C++ type. General spirit of JAVA_ARRAYS_TYPEMAPS is to cast individual array elements, not to rely on potentially incompatible pointer casts. diff --git a/Lib/java/arrays_java.i b/Lib/java/arrays_java.i...
Refcount (SmartPointer / Implicit conv) & threads
I'm going to close this as splitting this over two tickets doesn't seem helpful. I have copied the relevant info to the patch ticket.
FIX [ swig-Bugs-3541652 ] Refcount (SmartPointer / Implicit
Eliminate use of undocumented SWIG feature
[java] bad code generation for typedef'd enums
Closing in favour of https://github.com/swig/swig/issues/3012
Reproduced with current git master (6eb2560e8d7192a8302e90ca3426df9aceb6d2e2). I noticed that if we ignore the methods we don't want then it works - e.g. add this before the %include "classes.h";: %ignore return_float(float &f); This is at least consistent with how method hiding would work if the %extend method was actually added in C++, consider this: #include <iostream> class C { public: virtual void return_float(float &f) { f = 123; } float return_float() { float f; return_float(f); return f;...
The case where the value is a pointer type raised in the comments above is https://github.com/swig/swig/issues/2938 (and also https://sourceforge.net/p/swig/bugs/1235/ which I've closed as a duplicate of the ticket in the active bug tracker).
wsfulton: With the change discussed above the template would still be instantiated before being used as a base class - the idea is to allow having the %template EARLIER, in particular before the C++ template definition. This would address the current awkward situation where a %template directive needs to be in the middle of a third-party C++ header which is being wrapped. This means the %template directive would need to be stored and processed later. The exact point to process seems a bit tricky,...
Python, map of pointer
Same problem was reported in the github tracker so closing this as a duplicate: https://github.com/swig/swig/issues/2938
This patch fixes the example here, but seems a bit of a hack as it just allows anything to be passed for this parameter, but with the lowest typecheck precedence. Ideally we should actually check for what's accepted her, though the in typemap allows anything so maybe that's actually correct: diff --git a/Lib/lua/lua_fnptr.i b/Lib/lua/lua_fnptr.i index b4c663c5..8e67d8fb 100644 --- a/Lib/lua/lua_fnptr.i +++ b/Lib/lua/lua_fnptr.i @@ -115,6 +115,9 @@ void swiglua_ref_get(SWIGLUA_REF* pref){ %} +%typemap(typecheck,...
Looks like https://github.com/swig/swig/issues/197 may be the same issue.
Still reproducible with current git master. Also I came up with a much simpler reproducer: %module x %inline %{ typedef enum { BAZ1 } baz; void enumbugexample( baz const & ) { } %} Then: $ swig -c++ -python simplified.i $ grep 'enum baz' simplified_wrap.cxx enumbugexample((enum baz const &)*arg1); static swig_type_info _swigt__p_baz = {"_p_baz", "baz *|enum baz *", 0, 0, (void*)0, 0}; The const & seems to be needed. I notice the type info entry includes enum baz * which seems wrong too.
I noticed the problem reported here is actually documented in the manual: https://www.swig.org/Doc4.2/SWIGPlus.html#SWIGPlus_namespaces Because namespaces are flattened, it is possible for symbols defined in different namespaces to generate a name conflict in the target language. For example: namespace A { void foo(int); } namespace B { void foo(double); } When this conflict occurs, you will get an error message that resembles this: example.i:26. Error. 'foo' is multiply defined in the generated...
Still present in git shortly after 4.2.0. It also seems to fail even if %nspace N; is used with a target language with %nspace support.
Still reproducible with git master shortly after 4.2.0. Looking at this afresh, the two delete_v calls are OK as those are for the temporary v(1.1.1) and v(2,2,2) objects passed to the comp constructor. The essential problem here is that comp_a_get returns a Python v object which wraps a pointer to the C++ v a inside the temporary comp object, but then delete_comp is called before we call v_x_get on that v. For this to work it seems either a reference to comp needs to be kept by the v returned by...
Still happens with current git master (shortly after SWIG 4.2.0) except the error is now a TypeError: TypeError: Wrong number or type of arguments for overloaded function 'IntVec___setitem__'.
Still present in current git master (shortly after 4.2.0). SWIG now handles both these cases: void f(double param = i.d()); void f(double param = Outer::d()); However the case reported here with both a namespace and an object is still not handled.
Still present in current git master (shortly after 4.2.0). SWIG now handles both these cases, but still not the case reported here with both a namespace and an object: void f(double param = i.d()); ``` void f(double param = Outer::d()); ```
Problems with long/jlong and int64_t on 64-bit platforms
This recent commit (which will be in SWIG 4.2.0) looks like it addresses the remaining points here: commit 7bba06b03ef4529c542c3cf8364c382027aae000 Author: William S Fulton <wsf@fultondesigns.co.uk> Date: Wed Sep 27 07:46:53 2023 +0100 Java - SWIGWORDSIZE64 for long type Defining SWIGWORDSIZE64 now applies the (unsigned) long long typemaps to (unsigned) long for a better match on systems where long is 64-bits. Although size_t typemaps are now applied from the int typemaps instead of the long typemaps,...
Reproducible with git master 29367b31c8202c5cbe72e05927d77004636d6af9. Running with -debug-module 1 then -debug-module 2 it seems this happens somewhere in between those two stages: +++ class - 0x7f9380f74810 ---------------------------------------- | allows_typedef - "1" | firstChild - 0x7f9380f74950 | kind - "class" | lastChild - 0x7f9380f74d70 | module - 0x7f9380f73b30 | name - "Parser::Parser" | parentNode - 0x7f9380f73c50 | previousSibling - 0x7f9380f74670 | sym:name - "Parser" | sym:overname...
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type seems to be the current version of the link wsfulton gave above.
where does that int come from? Oh, that's my fault - I was experimenting with the testcase and had added an int parameter before the ...! The other issues still seem to be the case with current git master.
Still fails to parse with current git master.
Retesting with current git master I spotted a problem with how I was building the shared library - the reproducer still fails as given, but s/::ns/ns/g makes it work. So my "things seem to have got worse" above is bogus.
[tcl] Constants and enums - apply rule not working
I think that given this feature was removed 18 years ago we should just update the documentation to match reality. Reinstating these typemaps looks hard as they seem to use some magic via a parse typemap attribute which there's no longer any code to handle, and I can't see where it used to be handle, or any documentation as to what it did: %typemap(in,parse="I") int CONSTANT, unsigned int CONSTANT ""; I've remove the documentation in 10bab22248327642133fcb94a7a7c1eb5e041ab8. If someone wants to reinstate...
C++ memory leak of temporaries on exception
I fixed this same issue for Lua in 9ab9c716239d2855bdd6c0771e2e980c0767fb57, and https://github.com/swig/swig/issues/1981 is the same but for Go. There's a testcase exception_memory_leak for it so writing a _runme.pl for that would provide a regression test.
Lifecycle of pointers to 'concrete' sub-objects (C#-binding patch included)
It seems like the case which triggered this report was probably really due to incorrect code elsewhere. However it seems to me that when SWIG is checking if the object is null in such cases it would still be better for it do (object)obj == null (and similarly for some obj != null tests I see which the patch here doesn't address) as it really does want an exact null check and it isn't necessary to be calling an overloaded == in this case. Usually what SWIG currently does just incurs a small but avoidable...
[csharp] getCPtr should use object.ReferenceEquals
[csharp] getCPtr should use object.ReferenceEquals
[ruby] mixed case module names not handled correctly
https://github.com/rubocop/ruby-style-guide#snake-case-files adds evidence that what SWIG calls the "init name" ought to be lower case. According to that it perhaps ought to be open_babel here rather than openbabel for %module OpenBabel - SWIG does have CamelCase to snake_case conversion code so we could easily do that, and there's always -initname openbabel if that's what you really want. I think this should just apply to the auto-generated default, and an explicit -initname OpenBabel should allow...
I retested as there have been some using fixes recently and the cause of this looks to be using ClassC::MyFunc; in ClassD, but this is still reproducible with current git master (2e1506c1896f90456e5b3092ba7c7200c1b1e2e1): $ ../preinst-swig -c++ -java example.i $ grep -A3 'public double MyFunc(ClassX p)' ClassD.java public double MyFunc(ClassX p) { return exampleJNI.ClassD_MyFunc__SWIG_1(swigCPtr, this, ClassX.getCPtr(p), p); } public double MyFunc(ClassX p) { return exampleJNI.ClassD_MyFunc__SWIG_2(swigCPtr,...
Current git master (2e1506c1896f90456e5b3092ba7c7200c1b1e2e1) now emits two errors, but then still segfaults (with both the original and with = 0 removed to make it valid C++): ../preinst-swig -c++ -python test.i test.i:2: Warning 323: Recursive scope inheritance of 'A<(char,0)>'. test.i:2: Warning 323: Recursive scope inheritance of 'A< char,0 >'. Segmentation fault (core dumped) The crash is due to an infinite recursion, which this patch fixes: diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx...
[ruby] Segfault with "using" declaration with templates
This is fixed in current git master which generates code with Derived.fun in both chunks of code shown above. git bisect shows the commit fixing it as being: commit 49e60c7d5617f482026e8585d02ddc3f8244e2e5 Author: William S Fulton <wsf@fultondesigns.co.uk> Date: Sat Jun 24 11:43:15 2023 +0100 Fix directors and allprotected mode and using declarations. Fixes recently introduced seg fault, but this has never worked properly. Closes #2616 CHANGES.current | 5 ++++ Examples/test-suite/allprotected.i |...
Great - 2ff9da0ce625eabf0dde3ffeaec075eba2c733a8 was the exact commit fixing this for the record.
Reproduced with 5e1a37c6c562b7cb62c62e439c5b6b647e6d6df5 (retested because that commit fixes a copyctor bug).
Reproduced with 595009cf2ff952d963a663113e82b032c4fa770f.
I've opened a PR with that change: https://github.com/swig/swig/pull/2644
There have been some allprotected fixes recently, but this is still reproducible.
There have been some allprotected fixes recently, but this is still reproducible.
Looks like https://sourceforge.net/p/swig/bugs/879/ is closely related and probably the same issue.
Still reproducible. Looks like https://sourceforge.net/p/swig/bugs/1250/ is closely related and probably the same issue.
I've opened a PR with this patch to try to move things forwards: https://github.com/swig/swig/pull/2636
https://github.com/swig/swig/issues/1171 may be related.
Wrapping Intel IPP headers generates assertion.
I failed to fully revert my second attempt, and actually left the first fix in place, just without the testcase, so this really was fixed in SWIG 4.1.0 (and I've just confirmed that the original full example can be processed successfully with currently SWIG git master).
Fixed on git master by https://github.com/swig/swig/commit/26dfe3394810a72e85c4c52ee568ff44cfbcac76. Fix should be in 4.2.0. (https://github.com/swig/swig/issues/1881 seems to actually be slightly different as that's not fixed by this change)
%ignore not utilized for xml output
In https://github.com/swig/swig/issues/2213 @wsfulton said about -xml: XML isn't really a target language at all and it never will be! It's not much different to the -debug-top debug option which dumps internal parse tree information. The main difference is the format of the output. The Foo class appears in the output of swig -c++ -python -debug-top 1 Examples/test-suite/class_ignore.i (and similarly for -debug-top 2 to -debug-top 4) . So while -xml is essentially undocumented, I think this is working...
It's a two dimension array of function pointers if I've understood it correctly, though I'm not certain I have. Actually, I think it's a two dimensional array of pointers to int. Still reproducible. Possibly related to https://github.com/swig/swig/issues/142
SWIG tries to wrap va_list dumbly
Reflecting on this, I think the now-documented approach mentioned above is a reasonable solution. Also APIs I've seen which have a function taking va_list often also provide a corresponding varargs function too, and in such cases attempting to automatically wrap the va_list one by generating a varargs function and wrapping it would be actively unhelpful. It'd be nicer to not generate wrapper code which doesn't compile for functions taking va_list, but I don't think we have a way to avoid wrapping...
Ticket moved from /p/swig/feature-requests/93/
Ticket moved from /p/swig/feature-requests/62/
I think this is probably essentially the same as https://github.com/swig/swig/issues/2089
(Though the testcase needs tweaking slightly to actually define the enum (e.g. enum TestEnum { TESTENUM };) or else compilation gives an error: test_wrap.cxx:3159:8: error: use of enum ‘TestEnum’ without previous declaration 3159 | enum TestEnum; | ^~~~~~~~ with that adjustment the generated wrapper fails to compile with: g++ `python3-config --cflags` -fPIC -c test_wrap.cxx -o test_wrap.o test_wrap.cxx: In function ‘PyObject* _wrap_new_VecTestNum(PyObject*, PyObject*)’: test_wrap.cxx:3327:38: error:...
(Though the testcase needs tweaking slightly to actually define the enum (e.g. enum TestEnum { TESTENUM };) or else compilation gives an error: test_wrap.cxx:3159:8: error: use of enum ‘TestEnum’ without previous declaration 3159 | enum TestEnum; | ^~~~~~~~ with that adjustment the generated wrapper fails to compile with: g++ `python3-config --cflags` -fPIC -c test_wrap.cxx -o test_wrap.o test_wrap.cxx: In function ‘PyObject* _wrap_new_VecTestNum(PyObject*, PyObject*)’: test_wrap.cxx:3327:38: error:...
Still reproduces with current git master (b18b75369cd4b2795abad1283629b13a62630b58)
swig chokes on c++ template< template...> >
SWIG git master now processes the original example here. I suspect this is the fix (which will be in SWIG 4.2.0): 2022-12-02: wsfulton #624 #1021 Improved template template parameters support. Previously, specifying more than one simple template template parameter resulted in a parse error. Now multiple template template parameters are working including instantiation with %template. Example: template <template<template<class> class, class> class Op, template<class> class X, class Y> class C { ......
Reproduced with 8a24c19d2621e0de6a4429a039dc75d3a761acd4.
The two #define case was fixed in SWIG 4.0.0 (thanks to your report).
Support the director feature in Lua
I don't think it's helpful to keep this open indefinitely (especially as we migrated to github in 2013 and it seems I'm the only person still looking at open tickets here. Therefore I'm going to close this as "wontfix", though really it's more like "unlikely to be fixed unless someone who cares about having this feature works on it".