Simply ignore the const on them, to avoid ending up with an extra and
invalid "const" in the generated code.
This fixes director_pass_by_value and typemap_out_optimal unit tests
after the latest merge.
If C++ wrappers for a class are not generated because it uses multiple
inheritance, we can't generate the C++ wrappers for any classes deriving
from it neither, so don't do it.
This fixes failure in multiple_inheritance_overload unit test.
Unfortunately the changes of 26bf86322 (Use SWIG-specific for
non-overloaded synthesized functions too, 2021-11-09) did break some
existing code bases using SWIG as they hardcoded the old wrapper
function names.
So turn this off by default and add a global variable allowing to enable
this, which can be done for a specific language only. This is ugly but,
unfortunately, there is no way to use the Language object from the C
function Swig_MethodToFunction(), so the only alternative would be to
add another parameter to it, but it already has 6 of them, so it
wouldn't really be that much better.
See #2366, #2368, #2370.
The extra flexibility in expanding "#@" was considered inappropriate,
see the discussion in #2096, so revert the preprocessor part of the
changes of 5bf1497d7 (Allow customizing type mangling in SWIG
preprocessor, 2021-11-10).
This unfortunately means that the macros used in <attribute.i> don't
work for C backend any longer, so a previously passed unit test had to
be disabled.
This is consistent with the way this is done for the other backends and
allows to avoid overriding these variables for partialcheck target.
Co-Authored-By: Olly Betts <olly@survex.com>
This was inconsistent with all the other tests and the macro suffered
from several problems. Just drop it and use the standard macro with the
same name instead.
This undoes parts of a2dc2756c (Several major fixes for: arrays, static
members, member func.ptrs., exceptions, ... Lots of tests runs ok now.,
2009-04-13) that shouldn't have been done in the first place.
Move this function definition to cexcept.swg from the code and only
define it if SWIG_swig_check_DEFINED is not defined yet, which both
simplifies the code in C.cxx and makes exception handling code more
flexible, as it's now possible to predefine SWIG_swig_check_DEFINED
in the code injected into the "cxxheader" section to replace the default
implementation. Show an example of doing this in the documentation and
document handling exceptions with C API too.
The changes above required adding a new "cxxcode" section, corresponding
to the "implementation" part of C++ wrappers and defining a new
SWIG_CXX_WRAPPERS preprocessor symbol to allow only adding C++-specific
code when C++ wrappers are actually generated. Also improve the
documentation of the C-specific sections in the manual.
This ensures that global functions can also use C++ classes, enums etc
for their parameters and return types.
C++ wrappers for a couple of tests had to be disabled, but this is not
really a regression as wrapping global functions just made apparent
problems that were not visible before because the corresponding wrappers
were not created at all.
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 is much more convenient and allows checking if the shared pointer
is empty easily, unlike before, when it couldn't be done and adding
support for it would have required adding extra functions.
Also add a way to check whether an object is null in C++ wrappers of the
classes handled via shared pointers and static null() method for
creating null objects of such classes.
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.
Avoid unnecessary heap allocations, just use temporary variables.
Actually update the string parameters passed by pointer/non-const
reference. This requires the pointers passed to actually be non-const,
so update the C-specific unit test runme to use a char buffer instead of
a literal string.
Also simplify the code copying the string contents to just use strdup()
(if there are ever any platforms where this POSIX functions is not
available, we could just define it ourselves once instead of using
strlen() + malloc() + memcpy() manually twice).
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.
This allows different threads to use the same library concurrently
without corrupting each other's exceptions.
Note that this requires C++11 support for wrapper compilation too. If
this really turns out to be a problem, we could always just #define
thread_local as compiler-specific equivalent such as "__thread" for gcc
or "__declspec(thread)" for MSVC, which are available since forever.
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.
It is used as a prefix, but it's really just the name of the module, so
the new name is less confusing.
There also doesn't seem to be any need to copy/delete it, just keep a
pointer, it's not going to change.
No real changes.
Trying to create the same "runme" executable for both C and C++ examples
could result in errors when using parallel make, as one of the targets
could fail to write to the file being currently executed.
Using separate names works around this problem.
Support for the exception specifications using types was removed in
C++17 (and "throw ()" in C++20), so don't use them when using the C++
compiler any longer, as this broke the example with recent g++ versions
that use C++17 by default.
We still need them for SWIG, however, so use SWIG_THROW macro, defined
differently for SWIG and the compiler, to preserve the existing
behaviour.
Using %except might be a better idea, but would require more changes.
C++ wrappers still don't compile for about a hundred tests, but they do
compile for almost 500 more of them, so it's still valuable to be able
to check that there are no regressions for those that do work now.
Passing them by value doesn't seem to have any advantages, as the copy
will be made internally anyhow if the original function took them by
value and doing an extra one doesn't seem necessary, but does have a big
drawback of not compiling if the class doesn't define a copy ctor.
We can't rely on the default-generated copy ctor because it simply
copies the (possibly) owned pointer, resulting in double destruction if
it's ever used, so disable it completely unless it is explicitly
declared in the original class, in which case we can wrap it using the C
function wrapper defined for it.
Note that we probably should also wrap default-generated copy ctor of
the original class, if it has any, but currently we don't do it even at
C wrappers level, and so can't do it for C++ wrappers neither.
Replace C::getProxyName() with global get_c_proxy_name() and use it in
cxx_class_wrapper rather than relying on "proxyname" attribute being
already set because this might not be the case if the base class is
defined in another SWIG module just %import'ed from the current one: in
this case, the class is known, but no wrappers had been generated for it
yet, so "proxyname" for it is not set.
Note that, unlike getProxyName(), the new function doesn't bother with
always copying the string, as we may be sure it remains valid as it's
referenced by the node, as one of its attributes.
This allows the generated code to compile when different classes depend
on each other, as the class must be forward-declared to be mentioned at
all (as either parameter or return type) and fully defined in order to
be used in either role, as we need to use its ctor or call swig_self()
on it.
No real changes, just prepare for adding more File objects to be used
for C++ wrappers generation: we can't generate all of them in a single
pass because there may be dependencies between classes.
This required slightly changing the approach used for resolving types in
emit_member_function(), as we can't resolve the type and the casts
to/from it independently any more, but need to do both at once, as this
is required when it's done indirectly due to $typemap() expansion, and
we can't make "return" part of the returned wrapper as we could end with
multiple "returns".
So replace expr_wrapper with type_desc containing both the wrappers and
the type itself and add "return" in emit_member_function() itself for
non-void functions. Also use IIFE so that we can always just prepend
this "return" in the beginning.
Also connect things up so that C++-specific type resolution function is
used while C++ wrappers are being generated.
It's simpler to write tests in C++ rather than C and checking the
generated C++ API also checks the C API it uses underneath, so there is
no need to have both.
This fixes e.g. li_boost_shared_ptr unit test, which uses Space::Klass
that should be known as just Klass (inside the outer namespace) in the
generated C++ wrappers.
Disable them for the test suite, as plenty things don't work yet, but
there is already more than enough code to not want to add even more
fixes to the same commit.
After making this mistake too many times already, make sure it doesn't
happen again by requiring gcc to give an error for any attempt to pass
a non-trivial object to vararg functions such as Printv(), Printf(),
Swig_error() etc.
Write the wrapper types and declarations directly to f_wrappers_h,
without passing by an intermediate f_wrappers_h_body which just
complicated things unnecessarily.
This means that "extern "C" { ... }" is now around the functions
declarations only, and not around the types and the declarations, but
this seems like a desirable side effect.
No real changes.
Also explain better what each of them is used for and use scoped_dohptr
instead of deleting them manually.
Stop writing everything to f_begin, which didn't make any sense, and use
a separate f_wrappers_cxx object for the contents of the cxx output file.
No real changes.
For C++ tests, check header compilation using C++ compiler too, as this
detects constructs valid in C but invalid in C++ and will also be useful
for checking C++-specific parts of the headers that will be generated in
the future.
They are invalid in C++ and there shouldn't actually be any in valid
input, but they do occur in SWIG test suite.
Don't generate anything for them in the output, especially because doing
this is not really more complicated than using "enum_is_empty" field
that we had previously and might even be a tad simpler, as it doesn't
split the "{" and "}" output between two different functions.
Such declarations are invalid without specifying the underlying type
(which is only possible since C++11) and are useless anyhow, so just
don't bother emitting them.
Support compiling and running either _runme.c or _runme.cxx files for
the given test (but not both).
Add a simple C++ test file to check that it actually works.
The -namespace option provides a better way of using the wrapped API, so
drop the optional wrapper generation, which is useless when this option
is used and just generates many lines of unwanted junk in the header.
Update the test suite and the examples to compensate to not rely on
being able to define SWIG_DEFINE_WRAPPER_ALIASES and add -namespace
option to all C++ tests, as it's done for C# test suite, and update them
to use the correct prefix and also use the accessors for the global
variables rather than using them directly, as this is impossible when
namespace prefix is used (it would have been possible to define a
preprocessor symbol corresponding to the real variable name, but it's
arguably not worth it).
fixup! Remove wrapper aliases generation and use -namespace in the tests
These tests duplicate the other, more complex, existing unit tests, so
it's just not useful to have them at all any more (they could have been
useful at the very beginning of C backend development, when none of the
other tests worked).
No real changes, just keep everything in a single function because it is
more clear than having both it and functionWrapperCPPSpecificWrapper()
doing the same thing.
Use getCurrentClass() and other existing attributes to check if the
current node is inside a class or not (and hence is global), this is
more explicit and avoids confusion for static member functions that were
marked as being global in spite of being nested inside a class.
This avoids conflicts between functions synthesized by %extend when
adding static methods to an existing class, and the actual wrapper
functions generated by the backend.
This shouldn't result in any user-visible changes.
No real changes, just move the test for "code" to the outer scope to
facilitate the upcoming changes.
This commit is best viewed ignoring whitespace-only changes.
Using this option allows to prefix all exported symbols (functions,
enums and enum elements) with a prefix based on the given namespace.
Note that (global) variables can't be exported directly when using the
global namespace prefix, even if they are of C-compatible type.
These typemaps never worked, but this went unnoticed until now because
the nonsensical "ctype" expansion generated by them still compiled.
With types possibly having a namespace prefix, they didn't any longer,
so define them correctly for the objects using "$resolved_type" and
define the typemap for "void*[]" separately, as "$resolved_type" can't
be used for it.
Use the "type" naming format for the types mangled by "#@" and "##@"
preprocessor operators, in order to allow customizing them for a
particular backend.
This isn't used by any backend yet, so this doesn't change anything so
far.
Use the containing class name as prefix, and add the name of the enum
itself to the prefix for the scoped enums, instead of doing something
strange and semi-random that we did before, with prefixes including the
namespace (which should never be the case without "nspace" feature), but
not the scoped enum.
This also fixes renaming of enum elements, as a side effect, which
didn't work before, add run test for enum_rename unit test to prove it.
This became unused after the changes of fd3e76365 (Streamline and fix
returning objects by value, 2019-08-06) and allows to simplify code
further as we don't need to override static and non-static member
function handlers at all any more now.
Rename getGlobalWrapperName() to getFunctionWrapperName() and make it
work for all functions, not just global ones.
This means that we can test whether the function is global or not in a
single place instead of doing it in two different ones.
No real changes, just avoid some code duplication and add an optional
argument to reset() to make it more compatible with std::unique_ptr<>
and also more flexible.
This was done way back in f84342a30 (Modified parameter handling using
typemaps. 'Reference' example. Visibility hint now applies only to the
global functions., 2008-06-28), surely accidentally.
This is not necessary any longer after the previous commit and is better
than setting SWIG_FEATURES in the workflow file, as this resulted in
showing "-w524" in the name of C CI build since the changes of 04a6ad3bb
(Add SWIG_FEATURES into GHA name, 2021-10-21), which was a bit ugly.
This is a more logical name for this function, as it caches its return
value in "proxyname" attribute and doesn't really have much to do with
namespaces.
No real changes.
Use the same function in getNamespacedName() which was already used in
getGlobalWrapperName() just below, this is more readable and more clear
than just replacing dots with underscores as we did before.
Also use scoped_dohptr instead of manual Delete() calls.
No real changes.
No real changes, just make the code do what the comment said it did and
only use the namespace as prefix when "nspace" feature is on instead of
always trying to use it as prefix and then resetting it.
This required adding default ctor and assignment operator from raw
pointer to scoped_dohptr, but they can be useful elsewhere too, while
the actual code in getGlobalWrapperName() is simpler and more readable
now.
No real changes.
Defining the aliases by default results in conflicts when including
headers from multiple modules as e.g. SWIG_PendingException_get() is
defined in all of them, and could also easily result in other unwanted
clashes, so make this opt-in and update the examples and tests relying
on using the wrappers without the module prefix to define
SWIG_DEFINE_WRAPPER_ALIASES explicitly.
Don't include the entire file, including its header comment, into the
generated code, but just the part that we want to appear there.
This looks nicer and is also more explicit and hence clear.
Specify -pthread option which should be universally supported under
non-{MSW,Mac} platforms by now and which is required under Linux to link
the tests using boost::shared_ptr<>, which uses pthread_mutex_xxx().
Enable the tests and support of shared_ptr in them for C (which required
disabling a previously passing, because not doing anything, attributes
test which is currently broken for unrelated reasons).
Also undo the changes to common.mk originally done in this branch and
rendered unnecessary by de5e0c865 (C++11 testing moved to a configure
option, 2013-10-08) on master.
This test doesn't really work, as directors support is not implemented
at all in C backend, but remove it from here to prevent reports from
"make check-failing" about "failing test passing".
This is similar to be491506a (Java std::vector improvements for types
that do not have a default constructor., 2019-03-01) for Java, except we
don't have to bother with any compatibility constraints for this, not
yet used by anyone. module.
This reverts commit d89a95a48c as,
finally, it's not worth trying to use UTL typemaps from C: this required
bad hacks for std::vector and would be even worse for std::map, so don't
bother with them and just correct the "poor" C typemaps to be slightly
less poor and use them instead.
Use simple fixed typemap instead of trying to use the much more complex
one from the UTL which doesn't work for C.
Add a simple test case for std::map<>.
This is needed to find the SWIG-generated shared library when using C
too, as it's already the case for many (but, surprisingly, not all)
other target languages.
There doesn't seem to be any reason for using it rather than just
returning from main() as usual, and it provokes warnings about
implicitly declared function when compiling them.
They were not supported currently, but processing them resulted in just
a warning about missing ctype typemap and generated uncompilable code.
Give an error and don't generate any code at all now, which is more
clear and helpful.
Also exclude the part of kwargs_feature test using varargs from C test
suite.
The existing typemaps didn't work at all and making them work would
require defining all the typemaps needed by the Unified Typemaps
Library, which seems to be geared towards dynamic languages.
Just implement completely straightforward (and not very convenient to
use) typemaps instead.
Enable the now passing unit tests and add a runme for one of them.
Remove the code related to "_result_ref" which was confusing and plain
wrong, as it generated something that compiled but crashed during
run-time due to the use of a pointer to an already destroyed stack
object.
Instead, correct the "out" typemap to create a new copy of the object,
which mostly works fine on its own, except that it depends on using
SwigValueWrapper if necessary, so add the call to cplus_value_type()
does this. This also required removing the code resolving typedefs in
the "type" attribute because it confused the base class logic and still
needs an explicit cast to the actual return type due to the use of (and
probable bug in) get_wrapper_func_return_type().
These changes mean that "cppouttype" typemap is not used any longer, so
remove it too.
A couple more tests pass now.
Use "..." instead of "{...}" to avoid generating extra lines with
opening/closing curly braces, which are completely unnecessary.
Also remove an unnecessary "if" check in "in" typemap, which was
useless.
No real changes.
Prefix them with namespace-based prefix (e.g. "ns1_ns2_" for a function
inside ns1::ns2) if feature:nspace is on. Otherwise, or if the function
is defined in the global namespace, use the module name as prefix
instead of "_wrap": this is slightly less ugly and results in more
unique names.
Not being able to do it is too restrictive in practice and just forces
to use raw DOH pointers, which is not really less dangerous than adding
the assignment operator and reset() method to this class.
There doesn't seem to be any unit tests covering this, but the old code
was wrong because it didn't replace periods used as namespace separators
with underscores, which resulted in periods appearing in the output when
nested namespace were used.
Fix this and also reuse the now fixed getNamespacedName() in
getEnumName() which contained its own buggy version of the same code.
It doesn't seem necessary to muck with sym:name explicitly when we
construct the fully qualified name using getNamespacedName() later
anyhow.
Moreover, the overridden version had a bug which resulted in a crash in
template_empty_inherit unit test and simply removing it entirely allows
the test to pass (without breaking anything else).
This is done not so much to fix the memory leak per se (as there are
gazillions of other ones remaining), but to show that the return value
of getProxyName() does need to be freed, as this was unclear previously,
with it being freed in one place where this function was used, but not
in the other one, here.
Also state this explicitly in the function comment.
Handle char constants defined using #define or %constant correctly.
Also handle static member const variables, which didn't work at all
before, and quote values of such variables of char type.
It's not significantly simpler to use "goto" in this function, so just
replace it with "return".
Also remove the unnecessary checks for strings being deleted being
non-null, as they always are.
No real changes.
We need to make a copy instead of directly returning whatever sym::name
points to, as this value can be overwritten with something different
later, resulting in weird problems with the value of "proxyname"
attribute changing "on its own".
After this bug fix, a few more unit tests pass.
There is no need to check if the input is non-null, as the effect of
both branches of "if" is the same anyhow.
Also get rid of an extra and unnecessary block.
No real changes.
There is no need to override it just to call the base class version.
Also remove the outdated comment, as %extend is supported currently
(albeit with some bugs remaining).
No real changes.
Don't mark functions not intended to be overridden (nor overriding those
in the base class) as "virtual", this is useless and confusing.
No real changes.
By delegating to the base class instead we not only save quite a few
lines of code, but gain support for ctors/dtors defined using %extend,
which didn't work before, allowing to reenable some of the previously
failing tests.
This is useless and the C-specific version didn't handle template
methods added with %extend correctly, so removing this code also fixes
some (but not all yet) failures in extend_template_method.cpptest unit
test.
This is never going to work and just results in generating uncompilable
code.
In principle, we could either generate wrappers for these functions
while still handling the struct as a plain C struct, or switch to
generating class-like wrappers for it if it's %extended with any
functions, but for now just ignore them as this is the simplest thing to
do.
Incidentally, this makes the default_args_c test pass again now, after
the last merge with master pulled in such %extend directives into it.
SWIG_exit() is not declared anywhere, so would need to be explicitly
declared to avoid warnings, while exit() can be declared just by
including <stdlib.h>, so prefer to use the latter, especially because
they're one and the same anyhow.
They seem unnecessary too and look suspicious, notably the use of "static" in
the "out" typemap is almost certainly wrong.
As all the tests still pass without them, don't bother fixing these typemaps
but just remove them completely.
It's not clear why they were defined in the first place, but they broke
li_std_vector_ptr unit test, which now uses "T**", after the latest merge with
master, so just remove them to let the test pass again.
This didn't work correctly before because we need to override the base class
replaceSpecialVariables() method to expand $resolved_type, which appears
during the expansion, using the type supplied as $typemap() argument instead
of doing it later using it the type to which the typemap containing the macro
is attached.
This is a prerequisite for implementing smart pointers support.
This will allow implementing replaceSpecialVariables(): as it is called from
inside the typemap lookup code, we can't pass any parameters to it directly,
but we can use a class language-global member variable to it indirectly.
No real changes yet.
Don't create a new node just to delete it if we don't need it, but rather only
create it if we do need it.
Also copy as much as can be copied in copy_node() helper, it was confusing to
copy part of the attributes in it and part in the caller. And one of them
("c:inherited_from") was even copied twice, it was first created in the
function and then unconditionally overwritten by the caller -- don't do this
any more.
No real changes.
At the very least, this gives us a working vector<bool> and allows
"li_std_vector" unit test to pass. It is also just nice to reuse the existing
typemaps instead of having another copy of them.
As C doesn't have UTL, some parts of std_vector.i had to be excluded from it
however.
The existing typemaps didn't make much sense, simplify (there doesn't seem to
be any point in using $1_basetype when dealing with "bool") them and treat
"const bool&" as "bool", not as pointer, as this is much more convenient in C.
This also allows another unit test to pass.
Typedefs were not resolved for non-object types in spite of
SwigType_typedef_resolve_all() call as it didn't affect "c_parm_type".
Actually it is not even clear if resolving typedefs is a good idea as using
them probably makes the generated code more clear, but at least in the case of
nested typedefs we do need to do it as "Class::Type" can't appear in C code.
For some reason, the copy of the function made in the derived class used the
"name" attribute instead of "sym:name", which means that any %renames attached
to it were lost and didn't affect the derived class version.
Fix this and also a problem uncovered by doing it in the operator_overload
unit test as the assignment operator shouldn't be inherited at all, the
compiler-generated operator is used instead if the derived class doesn't
define its own one.
This function seemed to be doing a few unnecessary things, e.g. it resolved
the typedefs which doesn't seem to be necessary and the test for member
pointer seems to be useless too.
Just add a local "cppresult" directly in the caller instead of using a
separate function to do all this.
Using "sym:name" in the wrapping code is wrong, it is different from "name" if
the function has been renamed and we need to call the original C function, not
whichever name it is exported under.
Using longjmp was incompatible with using C++ objects in the code using the
wrappers, and using this C API from C++ to avoid ABI incompatibilities between
different C++ compilers is one of the main reasons for using this module.
Also, this required using a separate SwigObj instead of just using the real
object pointer which inevitably resulted in memory leaks whenever a non owned
object was returned from anywhere, e.g. from a member accessor or any method
returning pointer or reference.
Abandon the attempts to recreate C++ exceptions in C and just use a very
simple approach allowing to pass an error message out of band after any
function call in a global variable. An alternative could be to add a special
"out" error parameter to each and every function, but this risked being too
verbose, especially for the functions which don't really throw, and the calls
to SWIG_PendingException_get() won't need to be made explicitly when using a
C++ wrapper around the generated C API in the future.
This simplifies both the module and the generated code, in particular we don't
need any runtime code at all any more and there is no need for an extra level
of indirection for every object.
It also makes a couple more tests pass.
At the very least this results in clear error messages when running SWIG if
the symbol is encountered twice instead of errors given only when compiling
the generated code later.
The only remaining use of this attribute is to test for whether we're wrapping
a ctor and it is simpler and more clear to just check the node type directly
in this case.
This attribute was pretty confusing as it was used for parameters and entire
declarations, so removing it makes things more clear and simpler.
There is no need to set c:objstruct for the first parameter of the methods now
that we take care of it for disambiguating between overloads explicitly and
this function doesn't seem to be useful for anything else, simply drop it.
When building the unique suffix for each member of the overloaded functions
set, don't use the first "this" parameter of the object methods in it as it's
the same for all of them and so is completely useless for disambiguation
purposes and just results in unnecessarily long and ugly names.
Use "_const" suffix for the methods differing by their const-ness only, this
is necessary now that we don't use "_pFoo" or "_pcFoo" in their names.
This makes it superfluous to check for c:objstruct in
functionWrapperAppendOverloaded() (and checking for it there was not enough
neither, as the changes in the test suite show, sometimes the "this" parameter
type still found its way into the generated wrappers).
Just use our custom object creation/destruction code, but let the base class
do everything else.
This uncovered complete lack of support for ctors/dtors defined using %extend,
but this is not new and will have to remain broken for now.
This ensures that the pointer is not leaked.
Unfortunately it requires adding a dangerous, std::auto_ptr<>-like destructive
copy ctor to scoped_dohptr<>, but there is no better solution without C++11.
Reuse get_wrapper_func_proto() for the wrapper function definitions too, this
cuts down on the amount of duplicated code and also ensures that declarations
and definitions match.
Use the same ctype for wrapper declarations and definitions and just expand
$resolved_type differently in the two cases.
This simplifies the typemaps and ensures that the declarations and definitions
use the same types, at least for all non-object parameters.
We can always just use the "unconst" one because it works when the type is
used for a return value and is the same as the other one when it's used for a
parameter anyhow because top-level const is ignored in function signatures, so
don't bother defining two sets of macros when one will do.
In many (although perhaps not all, so don't suppress this warning
unconditionally) cases, there is no need for special typemaps in C, the
parameters can be just used directly, so this warning is harmless but it was
given many times during the test suite execution, distracting from more
important messages.
It is impossible to have two functions with the same name inside the same
program, but it is possible to provide a #define to allow the user code to use
the original function name for the wrapper function, so do it for convenience.
Remove the old changes adding explicit "_wrap_" prefix to the examples and the
tests and remove the few more now passing tests from the list of failing tests.
Don't give errors for the unknown types, instead wrap them using the mangled
name of the type.
This is the expected (even if not particularly useful) SWIG behaviour and
allows many more tests to pass.
The generated code, which used C++ scope operator "::" in a C header, didn't
compile and couldn't work anyhow.
Just use the accessor functions for not really global variables.
Although the default typemaps only use "resolved_type" for non-simple types,
the generic SWIGTYPE typemap can also be applied explicitly to other types as
"apply_strings" and "char_binary" unit tests do.
In this case just use the original type unchanged if we can, this is enough to
make these tests pass.
This is better than silently generating completely wrong code with
$resolved_type in it and makes it easier to understand what exactly went wrong
and where.
For some reason the test expected another bit field be changed when setting
the given one, which was just plain wrong and prevented the test from passing.
Don't refer to the typedef name (especially with a typo in it...), it is not
supposed to be exported.
Also fix the write() method call: use the right class for it and pass it the
correct arguments.
The sole reason for including this header seems to be to get size_t
declaration, so include the smallest header sufficient for this.
It would be even better to use a fragment for all size_t typemaps to only
include it if necessary, but it doesn't seem to be worth doing this right now.
Member function pointers can't possibly be represented as function pointers,
they have a strictly bigger size and attempting to do it resulted in code
which, with a lot of bad casts, compiled, but crashed during run-time.
The proper solution is to represent C++ method pointers with an appropriate
opaque type, but for now this remains broken -- just make it explicitly broken
instead of pretending that it works when it actually has no chance to.
Let "namespace_spaces" unit test pass, as it's not really related to the
function pointers, by adding an explicit SWIGC test to it.
There is no need to syntax check the header if it's going to be really used,
so this is a small optimization.
It also separates building of the wrappers from testing them better.
No real changes, just reuse the commands defined in the C section of the top
level Examples/Makefile instead of (imperfectly, i.e. CFLAGS was forgotten
here) duplicating them in Examples/test-suite/c/Makefile.
Output anonymous enums defined inside C structs in the global scope, this
doesn't change the semantics as the constants defined inside a struct still
have global scope in C, but avoids gcc warnings given when compiling the
generated code.
Don't force the caller to pass firstChild() of the struct node to this
function, just pass it the struct node itself and iterate over all of its
children inside it.
Pass void pointers directly to C, don't handle them objects which was done by
default previously because we didn't define any specific typemaps for them.
This allows to reenable another test.
Don't try to export the variables whose type can't be represented in C
directly, this can't work.
Instead, just let use the default implementation to generate wrapper functions
for them.
Update "cpp_basic_global_var_class" unit test accordingly and remove it from
the list of the failing tests.
Ensure that any commas inside SWIG_STR() used in "out" typemaps for class
types are not interpreted as macro argument separators by using an extra pair
of parenthesis around the type.
Catch errors in the generated headers even when we don't have a run test.
Unfortunately this uncovered that almost no unit tests actually pass, so many,
many more of them had to be disabled.
We just copied the function prototype without any changes from the original C
function to the wrappers header when in C mode, but this wasn't correct, e.g.
the original function could use typedefs not available in the wrapper.
Fix this by applying the typemaps in C mode too, but without the C++-specific
parts.
This also makes C and C++ code paths slightly less different from each other,
the long-term goal is to make them identical.
Enum element somehow lose the single quotes around them, compensate for it in
C module code (other modules use module-specific constvalue feature to work
around it, but it seems better to do it in SWIG itself rather than leaving the
user code to deal with it).
This finally makes the "enums" unit test pass.
Declare the variable as int as this is how variables of enum types are stored
(although this would have to be revised when support for C++11 base enum type
is added) and, although ugly, this at least allows the generated code to
compile.
This fixes some (but not all yet) errors in the "enums" and "cpp_enum" unit
tests.
Define enum type and enum values as the elements of this enum instead of using
preprocessor #defines for them.
This fixes a couple of enum-related unit tests.
Instead of hard coding two spaces, use "cindent" constant to make it more
clear what is the intended indentation of the generated code and also to make
it possible to change it later easily if desired.
Implement the check for duplicate SWIG_derives_from<> specializations which
could happen if a template type with default parameters was exported both with
implicit default values used for these parameters and the same values
specified explicitly.
This makes the code more complicated and is very rarely needed (in addition to
the above, the template class must also have a base class to trigger the bug),
but it does happen and used to work, so restore this after breaking it in the
last commit and reenable the template_default2 unit test.
Don't populate the typenames array for each and every created object and don't
search it when deleting every object, this is O(N) in number of classes and is
completely impractical for any big library where N can easily be several
thousands. Use destructor function which will correctly destroy the object
instead.
Also don't store each created objects in the global registry, there doesn't
seem to be any point in it.
And, in fact, don't bother with the typenames at all, just use another
pseudo-virtual function for checking whether a class inherits from a class
with the given name.
There is unfortunately one problem with the new approach: it doesn't work when
the same C++ type is wrapped under different names as this results in multiple
specializations of SWIG_derives_from<> for this type. But this is a relatively
rare situation (but which does arise in template_default2 unit test, which had
to be disabled) and could be fixed in the future by completely resolving the
type, including the default template parameters values, and checking if
SWIG_derives_from had been already specialized for it. In the meanwhile, this
regression is not a big deal compared to the advantages of the new approach.
The proxy layer, and all the extra complexity associated with it, seemed to be
only necessary in order to try to allow using the same name for the wrapped
global functions as were used for them in the original C or C++ code being
wrapped. However this could simply never work in all cases, notably it didn't
work at all when using ELF shared libraries under Unix as the functions with
the same name defined in the main program were interposed and replaced the
functions defined in the shared library, meaning that the proxy function foo()
called wrapper function _wrap_foo() which called back into proxy function
foo() itself again, resulting in guaranteed stack overflow. The only possible
way to fix this would be to use "protected" ELF visibility for the original
functions, but this is not always possible (e.g. if the sources of the
original library are not available) and not simple even when it is and,
besides, protected visibility has its own problems -- notably by making it
impossible to hook the library functions when you actually want to do it.
Besides, proxy-based approach simply couldn't work at all when using static
linking as it resulted in two copies of the function with the same name
Most importantly, however, the main task of this module is to wrap C++
classes, not C functions, and renaming them in the wrapper is not necessary at
all in this case as there is no conflict with the original names in this case.
So simply drop the idea of generating a separate proxy header and generate a
header declaring the functions declared in the wrapper instead and, also, do
not give them "_wrap_" prefix whenever possible, i.e. only do it for the
global functions.
This simplifies SWIG code itself and makes it simpler to use its output as
it's not necessary to link both with the wrapper (dynamically) and with the
proxy (statically) and it's not enough to link with the wrapper only and it
can be done in any way (i.e. either statically or dynamically).
As a side effect of this change, Swig_name_proxy() is not necessary any more
and was removed, eliminating the only difference with the master branch in any
source file other than c.cxx itself.
It doesn't make any sense to use protected visibility for the symbols in the
proxy code, the only use for it would be if it could be applied to the
original functions being wrapped, to prevent them from being shadowed by the
proxy versions, but this cannot be done, in general.
Apparently this was already understood as the code using SWIGPROTECT was
commented out, but ef85d0d43f didn't give any
reason for doing this, nor for leaving this code.
Assume there was none and just remove it completely now to avoid confusion.
Allow defining FAILING_{C,CPP,MULTI_CPP}_TESTS variables to exclude some tests
from the unit tests suite. This is useful to disable tests failing for some
language only.
Make "make check-c-examples" perform the correct build commands, e.g. not link
the proxy code into the shared library as this can't work because it defines
the same functions that are already present in it.
Also fix the c_xxx targets to work when SWIG is built in a separate build
directory.
Finally, simplify them by removing the unnecessary variables.
Notice that std_vector example still doesn't build, but at least now it is due
to a real problem in the C module and not makefile bugs.
2. -noexcept flag disables generating exception-related code (like array of type names in SwigObj, object registry, etc.). This can be used when we are sure we won't handle exceptions on the C side, and this will generate much less code.
3. Modified typemaps for object arrays. Multidimensional ones still needs some fixing.
4. Added 'enums' and 'cast_operator' runtime tests.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-maciekd@10771 626c5289-ae23-0410-ae9c-e8d60b6d4f22
<li><ahref="#C_basic_c_wrapping">Basic C wrapping</a>
<ul>
<li><ahref="#C_functions">Functions</a>
<li><ahref="#C_variables">Variables</a>
<li><ahref="#C_enums">Enums</a>
</ul>
<li><ahref="#C_basic_cpp_wrapping">Basic C++ wrapping</a>
<ul>
<li><ahref="#C_classes">Classes</a>
</ul>
<li><ahref="#C_exceptions">Exception handling</a>
<li><ahref="#C_cxx_wrappers">C++ wrappers</a>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG's support for creating ANSI C wrappers. This module has a special purpose and thus is different from most other modules.
</p>
<p>
<b>NOTE:</b> this module is still under development.
</p>
<H2><aname="C_overview"></a>36.1 Overview</H2>
<p>
SWIG is normally used to provide access to C or C++ libraries from target languages such as scripting languages or languages running on a virtual machine.
SWIG performs analysis of the input C/C++ library header files from which it generates further code. For most target languages this code consists of two layers; namely an intermediary C code layer and a set of language specific proxy classes and functions on top of the C code layer.
We could also think of C as just another target language supported by SWIG.
The aim then is to generate a pure ANSI C interface to the input C or C++ library and hence the C target language module.
</p>
<p>
With wrapper interfaces generated by SWIG, it is easy to use the functionality of C++ libraries inside application code written in C. This module may also be useful to generate custom APIs for a library, to suit particular needs, e.g. to supply function calls with error checking or to implement a "design by contract".
</p>
<p>
Flattening C++ language constructs into a set of C-style functions obviously comes with many limitations and inconveniences, but this module is actually also capable of generating C++ wrappers defined completely inline using the C functions, thus wrapping the original C++ library API in another, similar C++ API. Contrary to the natural initial reaction, this is far from being completely pointless, as wrapping C++ API in this way avoids all problems due to C++ ABI issues, e.g. it is now possible to use the original C++ API using a different C++ compiler, or a different version of the same compiler, or even the same compiler, but with different compilation options affecting the ABI. The C++ wrapper API is not identical to the original one, but strives to be as close to it as possible.
</p>
<H3>Known C++ Shortcomings in Generated C API:</H3>
<ul>
<li>Enums with a context like class or namespace are broken</li>
Consider the following simple example. Suppose we have an interface file like:
</p>
<divclass="code">
<pre>
/* File: example.i */
%module test
%{
#include "stuff.h"
%}
int fact(int n);
</pre>
</div>
<p>
To build a C module (C as the target language), run SWIG using the <tt>-c</tt> option :</p>
<divclass="shell"><pre>
$ swig -c example.i
</pre></div>
<p>
The above assumes C as the input language. If the input language is C++ add the <tt>-c++</tt> option:
</p>
<divclass="shell"><pre>
$ swig -c++ -c example.i
</pre></div>
<p>
Note that <tt>-c</tt> is the option specifying the <b>target</b> language and <tt>-c++</tt> controls what the <b>input</b> language is.
<p>
<p>
This will generate an <tt>example_wrap.c</tt> file or, in the latter case, <tt>example_wrap.cxx</tt> file, along with <tt>example_wrap.h</tt> (the same extension is used in both C and C++ cases for the last one). The names of the files are derived from the name of the input file by default, but can be changed using the <tt>-o</tt> and <tt>-oh</tt> options common to all language modules.
</p>
<p>
The <tt>xxx_wrap.c</tt> file contains the wrapper functions, which perform the main functionality of SWIG: each of the wrappers translates the input arguments from C to C++, makes calls to the original functions and marshals C++ output back to C data. The <tt>xxx_wrap.h</tt> header file contains the declarations of these functions as well as global variables.
</p>
<H3><aname="C_commandline"></a>36.2.2 Command line options</H3>
<p>
The following table list the additional command line options available for the C module. They can also be seen by using:
</p>
<divclass="shell"><pre>
$ swig -c -help
</pre></div>
<tablesummary="C specific options">
<tr>
<th>C specific options</th>
</tr>
<tr>
<td>-namespace <nspace></td>
<td>Generate wrappers with the prefix based on the provided namespace, e.g. if the option value is <tt>outer::inner</tt>, the prefix <tt>outer_inner_</tt> will be used. Notice that this is different from using SWIG <tt>nspace</tt> feature, as it applies the the prefix to all the symbols, regardless of the namespace they were actually declared in. Notably, this allows to export instantiations of templates defined in the <tt>std</tt> namespace, such as <tt>std::vector</tt>, using a custom prefix rather than <tt>std_</tt>.</td>
</tr>
<tr>
<td>-nocxx</td>
<td>Don't generate C++ wrappers, even when <tt>-c++</tt> option is used. See <ahref="#C_cxx_wrappers">C++ Wrappers</a> section for more details.</td>
</tr>
<tr>
<td>-noexcept</td>
<td>generate wrappers with no support of exception handling; see <ahref="#C_exceptions">Exceptions</a> chapter for more details </td>
</tr>
</table>
<H3><aname="C_dynamic"></a>36.2.3 Compiling a dynamic module</H3>
<p>
The next step is to build a dynamically loadable module, which we can link to our application. This can be done easily, for example using the <tt>gcc</tt> compiler (Linux, MinGW, etc.):
</p>
<divclass="shell"><pre>
$ swig -c example.i
$ gcc -c example_wrap.c
$ gcc -shared example_wrap.o -o libexample.so
</pre></div>
<p>
Or, for C++ input:
</p>
<divclass="shell"><pre>
$ swig -c++ -c example.i
$ g++ -c example_wrap.cxx
$ g++ -shared example_wrap.o -o libexample.so
</pre></div>
<p>
Now the shared library module is ready to use. Note that the name of the generated module is important: is should be prefixed with <tt>lib</tt> on Unix, and have the specific extension, like <tt>.dll</tt> for Windows or <tt>.so</tt> for Unix systems.
</p>
<H3><aname="C_using_module"></a>36.2.4 Using the generated module</H3>
<p>
The simplest way to use the generated shared module is to link it to the application code during the compilation stage. The process is usually similar to this:
</p>
<divclass="shell"><pre>
$ gcc runme.c -L. -lexample -o runme
</pre></div>
<p>
This will compile the application code (<tt>runme.c</tt>) and link it against the generated shared module. Following the <tt>-L</tt> option is the path to the directory containing the shared module. The output executable is ready to use. The last thing to do is to supply to the operating system the information of location of our module. This is system dependant, for instance Unix systems look for shared modules in certain directories, like <tt>/usr/lib</tt>, and additionally we can set the environment variable <tt>LD_LIBRARY_PATH</tt> (Unix) or <tt>PATH</tt> (Windows) for other directories.
</p>
<H2><aname="C_basic_c_wrapping"></a>36.3 Basic C wrapping</H2>
<p>
Wrapping C functions and variables is obviously performed in a straightforward way. There is no need to perform type conversions, and all language constructs can be preserved in their original form. However, SWIG allows you to enhance the code with some additional elements, for instance using <tt>check</tt> typemap or <tt>%extend</tt> directive.
</p>
<p>
It is also possible to output arbitrary additional code into the generated header by using <tt>%insert</tt> directive with <tt>cheader</tt> section, e.g.
For each C function declared in the interface file a wrapper function with a prefix, required to make its name different from the original one, is created. The prefix for the global functions is <tt>module_</tt>, i.e. the name of the SWIG module followed by underscore, by default. If <tt>-namespace</tt> option is used, the prefix corresponding to the given fixed namespace is used instead. If <tt>nspace</tt> feature is used, the prefix corresponding to the namespace in which the function is defined is used -- note that, unlike with <tt>-namespace</tt> option, this prefix can be different for different functions. The wrapper function performs a call to the original function, and returns its result.
</p>
<p>
For example, for function declaration in the module <tt>mymath</tt>:
</p>
<divclass="targetlang"><pre>
int gcd(int x, int y);
</pre></div>
<p>
The output is simply:
</p>
<divclass="targetlang"><pre>
int mymath_gcd(int arg1, int arg2) {
int result;
result = gcd(arg1,arg2);
return result;
}
</pre></div>
<p>
Now one might think, what's the use of creating such functions in C? The answer is, you can apply special rules to the generated code. Take for example constraint checking. You can write a "check" typemap in your interface file:
</p>
<divclass="code"><pre>
%typemap(check) int POSITIVE {
if ($1 <= 0)
fprintf(stderr, "Expected positive value in $name.\n");
}
int gcd(int POSITIVE, int POSITIVE);
</pre></div>
<p>
And now the generated result looks like:
</p>
<divclass="targetlang"><pre>
int _wrap_gcd(int arg1, int arg2) {
{
if (arg1 <= 0)
fprintf(stderr, "Expected positive value in gcd.\n");
}
{
if (arg1 <= 0)
fprintf(stderr, "Expected positive value in gcd.\n");
}
int result;
result = gcd(arg1,arg2);
return result;
}
</pre></div>
<p>
This time calling <tt>gcd</tt> with negative value argument will trigger an error message. This can save you time writing all the constraint checking code by hand.
Wrapping variables comes also without any special issues. All global variables are directly accessible from application code. There is a difference in the semantics of <tt>struct</tt> definition in C and C++. When handling C <tt>struct</tt>, SWIG simply rewrites its declaration. In C++ <tt>struct</tt> is handled as class declaration.
</p>
<p>
You can still apply some of the SWIG features when handling structs, e.g. <tt>%extend</tt> directive. Suppose, you have a C struct declaration:
</p>
<divclass="targetlang"><pre>
typedef struct {
int x;
char *str;
} my_struct;
</pre></div>
<p>
You can redefine it to have an additional fields, like:
</p>
<divclass="code"><pre>
%extend my_struct {
double d;
};
</pre></div>
<p>
In application code:
</p>
<divclass="targetlang"><pre>
struct my_struct ms;
ms.x = 123;
ms.d = 123.123;
</pre></div>
<H2><aname="C_basic_cpp_wrapping"></a>36.4 Basic C++ wrapping</H2>
<p>
The main reason of having the C module in SWIG is to be able to access C++ from C. In this chapter we will take a look at the rules of wrapping elements of the C++ language.
</p>
<p>
By default, SWIG attempts to build a natural C interface to your C/C++ code.
<tableBORDERsummary="Generated C representation of C++">
<tr>
<th>C++ Type</th>
<th>SWIG C Translation</th>
</tr>
<tr>
<td>Class <tt>Example</tt></td>
<td>Empty structure <tt>Example</tt></td>
</tr>
<tr>
<td>Public, mutable member variable <tt><tt>Foo Example::foo</tt></td>
<td><tt>
Example_foo_get(Example *e);</br>
Example_foo_set(Example *e, Foo *f);
</tt></td>
</tr>
<tr>
<td>Public, immutable member variable <tt><tt>Foo Example::bar</tt></td>
<td><tt>
Example_foo_get(Example *e);</br>
</tt></td>
</tr>
</table>
This section briefly covers the essential aspects of this wrapping.
</p>
<H3><aname="C_enums"></a>36.3.3 Enums</H3>
<p>
C enums and unscoped C++ enums are simply copied to the generated code and both the enum itself and its elements keep the same name as in the original code unless <tt>-namespace</tt> option is used or <tt>nspace</tt> feature is enabled, in which case the prefix corresponding to the specified namespace is used.
</p>
<p>
For scoped C++11 enums, the enum name itself is used as an additional prefix.
</p>
<H3><aname="C_classes"></a>36.4.1 Classes</H3>
<p>
Consider the following example. We have a C++ class, and want to use it from C code.
</p>
<divclass="targetlang"><pre>
class Circle {
public:
double radius;
Circle(double r) : radius(r) { };
double area(void);
};
</pre></div>
<p>
What we need to do is to create an object of the class, manipulate it, and finally, destroy it. SWIG generates C functions for this purpose each time a class declaration is encountered in the interface file.
</p>
<p>
The first two generated functions are used to create and destroy instances of class <tt>Circle</tt>. Such instances are represented on the C side as pointers to special structs, called <tt>SwigObj</tt>. They are all "renamed" (via typedef) to the original class names, so that you can use the object instances on the C side using pointers like:
</p>
<divclass="targetlang"><pre>
Circle *circle;
</pre></div>
<p>
The generated functions make calls to class' constructors and destructors, respectively. They also do all the necessary things required by the SWIG object management system in C.
</p>
<divclass="targetlang"><pre>
Circle * Circle_new(double r);
void Circle_delete(Circle * self);
</pre></div>
<p>
The class <tt>Circle</tt> has a public variable called <tt>radius</tt>. SWIG generates a pair of setters and getters for each such variable:
For each public method, an appropriate function is generated:
</p>
<divclass="targetlang"><pre>
double Circle_area(Circle * self);
</pre></div>
<p>
You can see that in order to use the generated object we need to provide a pointer to the object instance (struct <tt>Circle</tt> in this case) as the first function argument. In fact, this struct is basically wrapping pointer to the "real" C++ object.
Typecasts wrapper functions return values in proxy functions</br>
<code>
MyClass *MyClass_new(void) {</br>
return (MyClass *)MyClass_new();</br>
}
</code>
</td>
</tr>
<tr>
<td><tt>in</tt></td>
<td>Mapping of wrapper functions parameters to local C++ variables</br>
</br>
<code>
SwigObj* MyClass_do(SwigObj *carg1) {</br>
SomeCPPClass *arg1 = 0;</br>
if (carg1)</br>
arg1 = (SomeCPPClass*)carg1->obj</br>
else</br>
arg1 = 0;</br>
}
</code></td>
</tr>
<tr>
<td><tt>out</tt></td>
<td>Assigns wrapped function's return value to a dedicated return variable, packaging it into SwigObj if necessary</td>
</tr>
<tr>
<td><tt>cppouttype</tt></td>
<td>Type of the result variable used for the return value if the wrapped function is a C++ function
</td>
</tr>
<tr>
<td><tt>cxxintype</tt></td>
<td>Defines the type for the parameters of C++ wrapper functions corresponding to this type. By default is the same as <tt>ctype</tt>, but may sometimes be different to make the functions more convenient to use. For example, <tt>ctype</tt> for <tt>std::string</tt> is <tt>const char*</tt>, but <tt>cxxintype</tt> typemap for it is <tt>std::string const&</tt>, i.e. even though the C++ string passed as a raw pointer via C API, the C++ wrapper still accepts a C++ string. If this typemap is defined, <tt>cxxin</tt> should normally be defined as well. If it is not defined, <tt>ctype</tt> is used.
</td>
</tr>
<tr>
<td><tt>cxxouttype</tt></td>
<td>Similar to <tt>cxxintype</tt>, but is used for the function return values and together with <tt>cxxout</tt> typemap. Also defaults to <tt>ctype</tt> if not defined.
</td>
</tr>
<tr>
<td><tt>cxxin</tt></td>
<td>Defines how to transform <tt>cxxintype</tt> value to <tt>ctype</tt>
</td>
</tr>
<tr>
<td><tt>cxxout</tt></td>
<td>Defines how to transform <tt>ctype</tt> value returned by a function to <tt>cxxouttype</tt>
</td>
</tr>
<tr>
<td><tt>cxxcode</tt></td>
<td>May contain arbitrary code that will be injected in the declaration of the C++ wrapper class corresponding to the given type. Ignored for non-class types. The special variable <tt>$cxxclassname</tt> is replaced with the name of the class inside this typemap expansion and <tt>$cclassptrname</tt> is replaced with the name of the pointer type used to represent the class in C wrapper functions.
</td>
</tr>
</table>
<H3>C Typemaps, a Code Generation Walkthrough</H3>
To get a better idea of which typemap is used for which generated code, have a look at the following 'walk through'.</br>
Let's assume we have the following C++ interface file, we'd like to generate code for:
<H4>The Interface</H4>
<divclass="code"><pre>
%module example
%inline
%{
class SomeClass{};
template <typename T> class SomeTemplateClass{};
SomeClass someFunction(SomeTemplateClass<int>&someParameter, int simpleInt);
Any call to a C++ function may throw an exception, which cannot be caught by C code. Instead, the special <tt>SWIG_CException_get_pending()</tt> function must be called to check for this. If it returns a non-null pointer, <tt>SWIG_CException_msg_get()</tt> can be called to retrieve the error message associated with the exception. Finally, <tt>SWIG_CException_reset_pending()</tt> must be called to free the exception object and reset the current pending exception. Note that exception handling is much simpler when using C++, rather than C, wrappers, see sections 36.6.2.
</p>
<H2><aname="C_cxx_wrappers"></a>36.6 C++ Wrappers</H2>
<p>
When <tt>-c++</tt> command line option is used (and <tt>-nocxx</tt> one is not), the header file generated by SWIG will also contain the declarations of C++ wrapper functions and classes mirroring the original API. All C++ wrappers are fully inline, i.e. don't need to be compiled separately, and are always defined inside the namespace (or nested namespaces) specified by <tt>-namespace</tt> command-line option or the namespace with the same name as the SWIG module name if this option is not specified.
</p>
<p>
C++ wrappers try to provide a similar API to the original C++ API being wrapped, notably any class <tt>Foo</tt> in the original API appears as a class with the same name in the wrappers namespace, and has the same, or similar, public methods. A class <tt>Bar</tt> deriving from <tt>Foo</tt> also derives from it in the wrappers and so on. There are some differences with the original API, however. Some of them are due to fundamental limitations of the approach used, e.g.:
<ul>
<li>Only template instantiations are present in the wrappers, not the templates themselves.</li>
</ul>
Other ones are due to things that could be supported but haven't been implemented yet:
<ul>
<li>Only single, not multiple, inheritance is currently supported.</li>
<li>Only enums using <tt>int</tt> (or smaller type) as underlying type are supported.</li>
Generated C++ code can be customized by inserting custom code in the following sections:
<ul>
<li><tt>cxxheader</tt> for including additional headers and other declarations in the global scope.</li>
<li><tt>cxxcode</tt> for additional code to appear after the declarations of all wrapper classes, inside the module-specific namespace.</li>
</ul>
The following features are taken into account when generating C++ wrappers:
<ul>
<li><tt>cxxignore</tt> May be set to skip generation of C++ wrappers for the given function or class, while still generating C wrappers for them.</li>
</ul>
<H3>36.6.2 Exception handling</H3>
<p>
Exception handling in C++ is more natural, as the exceptions are re-thrown when using C++ wrappers and so can be caught, as objects of the special <tt>SWIG_CException</tt> type, using the usual <tt>try/catch</tt> statement. The objects of <tt>SWIG_CException</tt> class have <tt>code()</tt> and <tt>msg()</tt> methods, with the latter returning the error message associated with the exception.
</p>
<p>
If necessary, a custom exception type may be used instead of <tt>SWIG_CException</tt>. To do this, a custom implementation of <tt>swig_check()</tt> function, called to check for the pending exception and throw the corresponding C++ exception if necessary, must be provided and <tt>SWIG_swig_check_DEFINED</tt> preprocessor symbol must be defined to prevent the default implementation of this function from being compiled:
%typemap(in) short [ANY], int [ANY], long [ANY], long long [ANY], char [ANY], float [ANY], double [ANY], unsigned char [ANY] "$1 = ($1_basetype *) $input;"
%typemap(in) short * [ANY], int * [ANY], long * [ANY], long long * [ANY], char * [ANY], float * [ANY], double * [ANY] "$1 = ($1_basetype *) $input;"
// Typemap for smart pointer type itself: these are somewhat special because we represent empty shared pointers as null pointers at C level because there is
// no advantage in using a non-null pointer in this case, while testing for NULL is much simpler than testing whether a shared pointer is empty.
// Note that "&" here is required because "$1" ends up being SwigValueWrapper and not the shared pointer itself. This is wrong and should be fixed by disabling
// the use of SwigValueWrapper for shared pointers entirely, as it's never needed for them.