The type of the member may be incomplete, so generate the definitions of
these functions in a separate section, after declaring all the wrapper
classes, just as it was already done for the other functions.
This fixes compiling some of the previously failing tests in C++ mode.
Use the base type, not the full type, to deal with the special case of
references to pointers which are blacklisted by classLookup(), for some
reason, but can be represented at C wrappers level.
No real changes, just factor out the code for (non-special) functions
generation from emit_member_function() into a separate
cxx_function_wrapper class, so that it could be reused for the global
functions generation too.
We must use the string for the resolved type, i.e. after replacing
typedefs with their expansions, as otherwise typedefs could leak into
the generated header.
In principle it might be possible to actually use the original typedefs
in the C++ part of the wrappers, but then we'd need to propagate the
typedef definitions there too and we don't do it currently.
This is more consistent with lookup_cxx_ret_type() and makes using it
simpler.
Also move error reporting into this function itself as it could fail for
other reasons than missing "ctype" typemap too.
No real changes.
This is also not specific to class wrappers, but can, and will be, used
for the global functions, so move it to a place where it can be reused.
No changes yet.
This makes the typemap much more useful, as it can now reference the
name of the class it is being expanded for and the type of the C pointer
used by it (in principle, the latter could be recovered by using
decltype(), but this results in rather verbose code inside static
methods where a dummy pointer to the type must be constructed first, so
using another special variable seems like a simpler solution).
This makes using returning strings much simpler to use from C++ code as
the returned pointers don't have to be deleted manually -- although, of
course, this does require an extra allocation and copy and so should be
avoided for the very long strings.
Add a new runtime test showing how simple and convenient it is to use
the functions working with string using the C++ wrappers now.
This is similar to the last two commits for cxx_rtype_desc and uses a
more appropriate and more specific class for holding parameter type
description.
This is just a refactoring, no real changes yet.
Instead of using ad hoc terminology, just call the string used here a
typemap because this is what it actually is.
Also keep just a single function and prepend "$result =" to it
automatically if necessary, as this is more convenient.
Still no real changes, but this will make it simpler to add support for
user-specified cxxout typemap.
Maintaining just wrapper start/end fragments is too limiting, at least
for the return type, so allow making the "return action" a formatted
string in which the return value can be inserted at any place.
This will allow making return types more customizable in the upcoming
commits, but there are no changes yet, this is just a refactoring.
Add typecheck typemaps for primitive types and string and call
Swig_overload_check() to ensure that we don't generate two wrappers
functions taking the same "const char*" type if we have overloads taking
it and "std::string" (or a reference) in the original code.
Classes not deriving from another class in the hierarchy must take care
of freeing their current pointer before reassigning it.
This should have been part of 3f3438093 (Define move ctor and assignment
operator for C++ wrappers, 2021-11-24).
Only take ownership of the objects returned from functions that are
explicitly annotated with %newobject or from functions returning objects
by value -- as in this case nothing else can own the returned object
anyhow.
This required changing the code slightly to let do_resolve_type() access
the function node pointer, as the information we need is only available
in it and not in the dummy node passed to us when we're called from
inside Swig_typemap_lookup() due to $typemap() expansion.
Use enum types instead of int for the enum-valued parameters and
function return values, this is more type-safe and clear for the users
of the library.
Change cpp_enum unit test to use C++ to check that C++ enum wrappers
can at least be compiled, but still use C API in it.
Note that enum whose underlying type is bigger than int still don't
work, but this is no different from what it was before, so just document
this limitation but don't do anything else about it for now.
This commit is best viewed ignoring whitespace-only changes.
Also use sym:name even for typedefs for enums themselves, as they can
%renamed as well.
Note that this means that "tdname" itself should probably be never used
at all at this level, but it's still used for structs in C mode, which
is almost certainly wrong.
Ever since fb4d70027 (Represent enums as themselves in generated code,
2016-04-14) the code used "name" attribute for the enums themselves
instead of "sym:name". The reason for this was documented in the comment
added in f4ee8e536 (Fix names of enums and their elements, 2021-11-04),
but this explanation was only half-correct: although we indeed shouldn't
use sym:name for typedefs, we should use it for the enums themselves, as
otherwise renaming them didn't work and enums were generated in the
wrappers with the wrong names.
Fix this by using sym:name for non typedef'd enums.
This error message should never happen, normally, but still make it more
informative if it does, as it could be just completely useless if there
was no sym:name attribute on the node (as is often the case for the
function parameters, for example).
For now still use prefix for them, as otherwise enum element names may
conflict with the other names defined in the same scope.
The upcoming commits will handle them as scoped enums in the wrappers
too.
This doesn't seem to be more difficult to do, just ensure that the
nested enums use the proper indentation and output them in the section
containing the class declaration, rather than the global ones.
They are almost identical to C enums, but are more convenient to use
from C++ code, as the (possibly long) prefix doesn't need to be fully
specified if namespace using directive is used.
For now restrict the wrapper enums generation to global enums only.
Use enum_prefix_, ending with "_" if it's not empty, as it can be used
unconditionally instead of having to check whether it's null every time
first.
No real changes, this is just a simplification.
Don't bother with maybe_owned_dohptr, we can just use tdname directly at
the cost of a single "if" at the end, so do it like this as it's more
clear and shorter.
Don't use "f_" prefix and "File *" type for the variables that are
strings and not files. Use "sect_" prefix, which means "section", and
"String *" for them.
This finally stops using misleading types (even if they all map to
"void*" anyhow) for the variables, which could result in using file-only
functions with non-files or string-only functions (e.g. Append()) with
two "f_" variables, only for it to work with one of them but not the
other (which was a real file, unlike the first one).
No real changes, this just clarifies the types.
The approach of the parent commit almost worked, but broke down if the
main module itself redefined typemaps for SWIGTYPE, as this broke
generation of SWIG_CException wrappers when we finally did it at the
end.
This probably could be salvaged by explicitly defining the typemaps for
SWIG_CException itself and also "int" and "char*", used for its
functions, but this just seems too fragile so switch to a different
approach instead: examine the parse tree immediately when starting
generation to check if it contains any %imports, and decide whether we
need to generate exceptions support in this module based on this.
New version seems more robust and easier to understand, and is probably
not noticeably slower.
Still keep the one in the previous commit just in case we need/want to
return to it later -- but keep in min the typemap redefinition problem
described above if we do it.
Ensure that we have only a single SWIG_CException_Raise() function
across all modules instead of having per-module functions and, worse,
per-module PendingException variables, which resulted in compile-time
errors and couldn't work anyhow because function checking for the
current exception didn't necessarily use the same "global" variable
where it was stored. More formally, old version resulted in ODR
violations and undefined behaviour.
The way we avoid it now is rather ugly and consists in excluding
SWIG_CException from wrapping using the hack in the source code which
postpones wrapping this class until the very end and checks if we had
encountered any %import directives and simply doesn't wrap it if we did.
The same code is used to define the special SWIG_CException_DEFINED
preprocessor symbol which is then used in the generated code to prevent
the SWIG_CException class declaration from being compiled as part of the
wrapper too (because this still happens due to %inline being used for
its definition, and there doesn't seem to be any better way to avoid
this).
This is definitely not pretty, but at least adding "throw(char*)" to a
couple of functions in mod_[ab].i test suite files works now instead of
failing (even without linking and running) as before. This commit
doesn't modify the test suite to avoid possible problems with the other
languages, however.
Check for the pending exception after every call to a wrapper function
not marked "noexcept" and throw a C++ exception if necessary.
Add C++ version of the exception example to show how this works.
Also change SWIG_CException to use member functions for checking for and
resetting pending exceptions, this seems better than having separate
functions for it and will make it easier to customize exception handling
later by just replacing SWIG_CException class with something else.
Note that we still use a global (and not a member) function for raising
the exception, but this one is not exported at all, and needs to be a
function in order to be easily callable from other modules (see the
upcoming commit).
Don't bother finding the "top" node when we can just save the contents
of its "outfile_h" attribute in top(), where we already use it (and we
already save the module name).
No real changes, just make the code simpler and marginally faster.
This commit is best viewed ignoring whitespace-only changes.
We need the types from the imported modules, so #include the header
generated for it.
Unfortunately we have to half-guess the name used for that header, as
it's not available anywhere (and can't really be, as it could be changed
by a command line option used for another SWIG invocation that was used
to compile that module), but this seems to work well enough in practice.
In particular, this fixes failures in multi cpp tests, so that we don't
need FAILING_MULTI_CPP_TESTS any longer.