/Doc/Manual/SWIGPlus.html
HTML | 4913 lines | 4131 code | 774 blank | 8 comment | 0 complexity | b56b941aec17b1b86722593c3e68a2ea MD5 | raw file
Possible License(s): 0BSD, GPL-2.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>SWIG and C++</title>
- <link rel="stylesheet" type="text/css" href="style.css">
- </head>
- <body bgcolor="#ffffff">
- <H1><a name="SWIGPlus"></a>6 SWIG and C++</H1>
- <!-- INDEX -->
- <div class="sectiontoc">
- <ul>
- <li><a href="#SWIGPlus_nn2">Comments on C++ Wrapping</a>
- <li><a href="#SWIGPlus_nn3">Approach</a>
- <li><a href="#SWIGPlus_nn4">Supported C++ features</a>
- <li><a href="#SWIGPlus_nn5">Command line options and compilation</a>
- <li><a href="#SWIGPlus_nn38">Proxy classes</a>
- <ul>
- <li><a href="#SWIGPlus_nn39">Construction of proxy classes</a>
- <li><a href="#SWIGPlus_nn40">Resource management in proxies</a>
- <li><a href="#SWIGPlus_nn41">Language specific details</a>
- </ul>
- <li><a href="#SWIGPlus_nn6">Simple C++ wrapping</a>
- <ul>
- <li><a href="#SWIGPlus_nn7">Constructors and destructors</a>
- <li><a href="#SWIGPlus_nn8">Default constructors, copy constructors and implicit destructors</a>
- <li><a href="#SWIGPlus_nn9">When constructor wrappers aren't created</a>
- <li><a href="#SWIGPlus_nn10">Copy constructors</a>
- <li><a href="#SWIGPlus_nn11">Member functions</a>
- <li><a href="#SWIGPlus_nn12">Static members</a>
- <li><a href="#SWIGPlus_member_data">Member data</a>
- </ul>
- <li><a href="#SWIGPlus_default_args">Default arguments</a>
- <li><a href="#SWIGPlus_nn15">Protection</a>
- <li><a href="#SWIGPlus_nn16">Enums and constants</a>
- <li><a href="#SWIGPlus_nn17">Friends</a>
- <li><a href="#SWIGPlus_nn18">References and pointers</a>
- <li><a href="#SWIGPlus_nn19">Pass and return by value</a>
- <li><a href="#SWIGPlus_nn20">Inheritance</a>
- <li><a href="#SWIGPlus_nn21">A brief discussion of multiple inheritance, pointers, and type checking</a>
- <li><a href="#SWIGPlus_overloaded_methods">Wrapping Overloaded Functions and Methods</a>
- <ul>
- <li><a href="#SWIGPlus_nn24">Dispatch function generation</a>
- <li><a href="#SWIGPlus_nn25">Ambiguity in Overloading</a>
- <li><a href="#ambiguity_resolution_renaming">Ambiguity resolution and renaming</a>
- <li><a href="#SWIGPlus_nn27">Comments on overloading</a>
- </ul>
- <li><a href="#SWIGPlus_nn28">Wrapping overloaded operators</a>
- <li><a href="#SWIGPlus_class_extension">Class extension</a>
- <li><a href="#SWIGPlus_nn30">Templates</a>
- <li><a href="#SWIGPlus_nn31">Namespaces</a>
- <li><a href="#SWIGPlus_renaming_templated_types_namespaces">Renaming templated types in namespaces</a>
- <li><a href="#SWIGPlus_exception_specifications">Exception specifications</a>
- <li><a href="#SWIGPlus_catches">Exception handling with %catches</a>
- <li><a href="#SWIGPlus_nn33">Pointers to Members</a>
- <li><a href="#SWIGPlus_nn34">Smart pointers and operator->()</a>
- <li><a href="#SWIGPlus_nn35">Using declarations and inheritance</a>
- <li><a href="#SWIGPlus_nested_classes">Nested classes</a>
- <li><a href="#SWIGPlus_nn37">A brief rant about const-correctness</a>
- <li><a href="#SWIGPlus_nn42">Where to go for more information</a>
- </ul>
- </div>
- <!-- INDEX -->
- <p>
- This chapter describes SWIG's support for wrapping C++. As a prerequisite,
- you should first read the chapter <a href="SWIG.html#SWIG">SWIG Basics</a> to see
- how SWIG wraps ANSI C. Support for C++ builds upon ANSI C
- wrapping and that material will be useful in understanding this chapter.
- </p>
- <H2><a name="SWIGPlus_nn2"></a>6.1 Comments on C++ Wrapping</H2>
- <p>
- Because of its complexity and the fact that C++ can be
- difficult to integrate with itself let alone other languages, SWIG
- only provides support for a subset of C++ features. Fortunately,
- this is now a rather large subset.
- </p>
- <p>
- In part, the problem with C++ wrapping is that there is no
- semantically obvious (or automatic ) way to map many of its advanced
- features into other languages. As a simple example, consider the
- problem of wrapping C++ multiple inheritance to a target language with
- no such support. Similarly, the use of overloaded operators and
- overloaded functions can be problematic when no such capability exists
- in a target language.
- </p>
- <p>
- A more subtle issue with C++ has to do with the way that some C++
- programmers think about programming libraries. In the world of SWIG,
- you are really trying to create binary-level software components for
- use in other languages. In order for this to work, a "component" has
- to contain real executable instructions and there has to be some kind
- of binary linking mechanism for accessing its functionality. In
- contrast, C++ has increasingly relied upon generic programming and
- templates for much of its functionality.
- Although templates are a powerful feature, they are largely orthogonal
- to the whole notion of binary components and libraries. For example,
- an STL <tt>vector</tt> does not define any kind of binary object for
- which SWIG can just create a wrapper. To further complicate matters,
- these libraries often utilize a lot of behind the scenes magic in
- which the semantics of seemingly basic operations (e.g., pointer
- dereferencing, procedure call, etc.) can be changed in dramatic and
- sometimes non-obvious ways. Although this "magic" may present few
- problems in a C++-only universe, it greatly complicates the problem of
- crossing language boundaries and provides many opportunities to shoot
- yourself in the foot. You will just have to be careful.
- </p>
- <H2><a name="SWIGPlus_nn3"></a>6.2 Approach</H2>
- <p>
- To wrap C++, SWIG uses a layered approach to code generation.
- At the lowest level, SWIG generates a collection of procedural ANSI-C style
- wrappers. These wrappers take care of basic type conversion,
- type checking, error handling, and other low-level details of the C++ binding.
- These wrappers are also sufficient to bind C++ into any target language
- that supports built-in procedures. In some sense, you might view this
- layer of wrapping as providing a C library interface to C++.
- On top of the low-level procedural (flattened) interface, SWIG generates proxy classes
- that provide a natural object-oriented (OO) interface to the underlying code. The proxy classes are typically
- written in the target language itself. For instance, in Python, a real
- Python class is used to provide a wrapper around the underlying C++ object.
- </p>
- <p>
- It is important to emphasize that SWIG takes a deliberately
- conservative and non-intrusive approach to C++ wrapping. SWIG does not
- encapsulate C++ classes inside a special C++ adaptor, it does not rely
- upon templates, nor does it add in additional C++ inheritance when
- generating wrappers. The last thing that most C++ programs need is
- even more compiler magic. Therefore, SWIG tries to maintain a very
- strict and clean separation between the implementation of your C++
- application and the resulting wrapper code. You might say that SWIG
- has been written to follow the principle of least surprise--it does
- not play sneaky tricks with the C++ type system, it doesn't mess with
- your class hierarchies, and it doesn't introduce new semantics.
- Although this approach might not provide the most seamless integration
- with C++, it is safe, simple, portable, and debuggable.
- </p>
- <p>
- Some of this chapter focuses on the low-level procedural interface to
- C++ that is used as the foundation for all language modules. Keep in
- mind that the target languages also provide the high-level OO interface via
- proxy classes. More detailed coverage can be found in the documentation
- for each target language.
- </p>
- <H2><a name="SWIGPlus_nn4"></a>6.3 Supported C++ features</H2>
- <p>
- SWIG currently supports most C++ features including the following:</p>
- <ul>
- <li>Classes
- <li>Constructors and destructors
- <li>Virtual functions
- <li>Public inheritance (including multiple inheritance)
- <li>Static functions
- <li>Function and method overloading
- <li>Operator overloading for many standard operators
- <li>References
- <li>Templates (including specialization and member templates)
- <li>Pointers to members
- <li>Namespaces
- <li>Default parameters
- <li>Smart pointers
- </ul>
- <p>
- The following C++ features are not currently supported:</p>
- <ul>
- <li>Overloaded versions of certain operators (new, delete, etc.)
- <li>Nested classes, see <a href="#SWIGPlus_nested_classes">Nested classes</a> for workarounds.
- </ul>
- <p>
- As a rule of thumb, SWIG should not be used on raw C++ source files, use header files only.
- </p>
- <p>
- SWIG's C++ support is an ongoing project so some of these limitations may be lifted
- in future releases. However, we make no promises. Also, submitting a bug report is a very
- good way to get problems fixed (wink).
- </p>
- <H2><a name="SWIGPlus_nn5"></a>6.4 Command line options and compilation</H2>
- <p>
- When wrapping C++ code, it is critical that SWIG be called with the
- `<tt>-c++</tt>' option. This changes the way a number of critical
- features such as memory management are handled. It
- also enables the recognition of C++ keywords. Without the <tt>-c++</tt>
- flag, SWIG will either issue a warning or a large number of syntax
- errors if it encounters C++ code in an interface file.</p>
- <p>
- When compiling and linking the resulting wrapper file, it is normal
- to use the C++ compiler. For example:
- </p>
- <div class="shell">
- <pre>
- $ swig -c++ -tcl example.i
- $ c++ -c example_wrap.cxx
- $ c++ example_wrap.o $(OBJS) -o example.so
- </pre>
- </div>
- <p>
- Unfortunately, the process varies slightly on each platform. Make sure
- you refer to the documentation on each target language for further
- details. The SWIG Wiki also has further details.
- </p>
- <b>Compatibility Note:</b> Early versions of SWIG generated just a flattened low-level C style API to C++ classes by default.
- The <tt>-noproxy</tt> commandline option is recognised by many target languages and will generate just this
- interface as in earlier versions.
- <H2><a name="SWIGPlus_nn38"></a>6.5 Proxy classes</H2>
- <p>
- In order to provide a natural mapping from C++ classes to the target language classes, SWIG's target
- languages mostly wrap C++ classes with special proxy classes. These
- proxy classes are typically implemented in the target language itself.
- For example, if you're building a Python module, each C++ class is
- wrapped by a Python proxy class. Or if you're building a Java module, each
- C++ class is wrapped by a Java proxy class.
- </p>
- <H3><a name="SWIGPlus_nn39"></a>6.5.1 Construction of proxy classes</H3>
- <p>
- Proxy classes are always constructed as an extra layer of wrapping that uses low-level
- accessor functions. To illustrate, suppose you had a
- C++ class like this:
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- Foo();
- ~Foo();
- int bar(int x);
- int x;
- };
- </pre>
- </div>
- <p>
- Using C++ as pseudocode, a proxy class looks something like this:
- </p>
- <div class="code">
- <pre>
- class FooProxy {
- private:
- Foo *self;
- public:
- FooProxy() {
- self = new_Foo();
- }
- ~FooProxy() {
- delete_Foo(self);
- }
- int bar(int x) {
- return Foo_bar(self,x);
- }
- int x_get() {
- return Foo_x_get(self);
- }
- void x_set(int x) {
- Foo_x_set(self,x);
- }
- };
- </pre>
- </div>
- <p>
- Of course, always keep in mind that the real proxy class is written in the target language.
- For example, in Python, the proxy might look roughly like this:
- </p>
- <div class="targetlang">
- <pre>
- class Foo:
- def __init__(self):
- self.this = new_Foo()
- def __del__(self):
- delete_Foo(self.this)
- def bar(self,x):
- return Foo_bar(self.this,x)
- def __getattr__(self,name):
- if name == 'x':
- return Foo_x_get(self.this)
- ...
- def __setattr__(self,name,value):
- if name == 'x':
- Foo_x_set(self.this,value)
- ...
- </pre>
- </div>
- <p>
- Again, it's important to emphasize that the low-level accessor functions are always used by the
- proxy classes.
- Whenever possible, proxies try to take advantage of language features that are similar to C++. This
- might include operator overloading, exception handling, and other features.
- </p>
- <H3><a name="SWIGPlus_nn40"></a>6.5.2 Resource management in proxies</H3>
- <p>
- A major issue with proxies concerns the memory management of wrapped objects. Consider the following
- C++ code:
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- Foo();
- ~Foo();
- int bar(int x);
- int x;
- };
- class Spam {
- public:
- Foo *value;
- ...
- };
- </pre>
- </div>
- <p>
- Consider some script code that uses these classes:
- </p>
- <div class="targetlang">
- <pre>
- f = Foo() # Creates a new Foo
- s = Spam() # Creates a new Spam
- s.value = f # Stores a reference to f inside s
- g = s.value # Returns stored reference
- g = 4 # Reassign g to some other value
- del f # Destroy f
- </pre>
- </div>
- <p>
- Now, ponder the resulting memory management issues. When objects are
- created in the script, the objects are wrapped by newly created proxy
- classes. That is, there is both a new proxy class instance and a new
- instance of the underlying C++ class. In this example, both
- <tt>f</tt> and <tt>s</tt> are created in this way. However, the
- statement <tt>s.value</tt> is rather curious---when executed, a
- pointer to <tt>f</tt> is stored inside another object. This means
- that the scripting proxy class <em>AND</em> another C++ class share a
- reference to the same object. To make matters even more interesting,
- consider the statement <tt>g = s.value</tt>. When executed, this
- creates a new proxy class <tt>g</tt> that provides a wrapper around the
- C++ object stored in <tt>s.value</tt>. In general, there is no way to
- know where this object came from---it could have been created by the
- script, but it could also have been generated internally. In this
- particular example, the assignment of <tt>g</tt> results in a second
- proxy class for <tt>f</tt>. In other words, a reference to <tt>f</tt>
- is now shared by two proxy classes <em>and</em> a C++ class.
- </p>
- <p>
- Finally, consider what happens when objects are destroyed. In the
- statement, <tt>g=4</tt>, the variable <tt>g</tt> is reassigned. In
- many languages, this makes the old value of <tt>g</tt> available for
- garbage collection. Therefore, this causes one of the proxy classes
- to be destroyed. Later on, the statement <tt>del f</tt> destroys the
- other proxy class. Of course, there is still a reference to the
- original object stored inside another C++ object. What happens to it?
- Is the object still valid?
- </p>
- <p>
- To deal with memory management problems, proxy classes provide an API
- for controlling ownership. In C++ pseudocode, ownership control might look
- roughly like this:
- </p>
- <div class="code">
- <pre>
- class FooProxy {
- public:
- Foo *self;
- int thisown;
- FooProxy() {
- self = new_Foo();
- thisown = 1; // Newly created object
- }
- ~FooProxy() {
- if (thisown) delete_Foo(self);
- }
- ...
- // Ownership control API
- void disown() {
- thisown = 0;
- }
- void acquire() {
- thisown = 1;
- }
- };
- class FooPtrProxy: public FooProxy {
- public:
- FooPtrProxy(Foo *s) {
- self = s;
- thisown = 0;
- }
- };
- class SpamProxy {
- ...
- FooProxy *value_get() {
- return FooPtrProxy(Spam_value_get(self));
- }
- void value_set(FooProxy *v) {
- Spam_value_set(self,v->self);
- v->disown();
- }
- ...
- };
- </pre>
- </div>
- <p>
- Looking at this code, there are a few central features:
- </p>
- <ul>
- <li>Each proxy class keeps an extra flag to indicate ownership. C++ objects are only destroyed
- if the ownership flag is set.
- </li>
- <li>When new objects are created in the target language, the ownership flag is set.
- </li>
- <li>When a reference to an internal C++ object is returned, it is wrapped by a proxy
- class, but the proxy class does not have ownership.
- </li>
- <li>In certain cases, ownership is adjusted. For instance, when a value is assigned to the member of
- a class, ownership is lost.
- </li>
- <li>Manual ownership control is provided by special <tt>disown()</tt> and <tt>acquire()</tt> methods.
- </li>
- </ul>
- <p>
- Given the tricky nature of C++ memory management, it is impossible for proxy classes to automatically handle
- every possible memory management problem. However, proxies do provide a mechanism for manual control that
- can be used (if necessary) to address some of the more tricky memory management problems.
- </p>
- <H3><a name="SWIGPlus_nn41"></a>6.5.3 Language specific details</H3>
- <p>
- Language specific details on proxy classes are contained in the chapters describing each target language. This
- chapter has merely introduced the topic in a very general way.
- </p>
- <H2><a name="SWIGPlus_nn6"></a>6.6 Simple C++ wrapping</H2>
- <p>
- The following code shows a SWIG interface file for a simple C++
- class.</p>
- <div class="code"><pre>
- %module list
- %{
- #include "list.h"
- %}
- // Very simple C++ example for linked list
- class List {
- public:
- List();
- ~List();
- int search(char *value);
- void insert(char *);
- void remove(char *);
- char *get(int n);
- int length;
- static void print(List *l);
- };
- </pre></div>
- <p>
- To generate wrappers for this class, SWIG first reduces the class to a collection of low-level C-style
- accessor functions which are then used by the proxy classes.
- </p>
- <H3><a name="SWIGPlus_nn7"></a>6.6.1 Constructors and destructors</H3>
- <p>
- C++ constructors and destructors are translated into accessor
- functions such as the following :</p>
- <div class="code"><pre>
- List * new_List(void) {
- return new List;
- }
- void delete_List(List *l) {
- delete l;
- }
- </pre></div>
- <H3><a name="SWIGPlus_nn8"></a>6.6.2 Default constructors, copy constructors and implicit destructors</H3>
- <p>
- Following the C++ rules for implicit constructor and destructors, SWIG
- will automatically assume there is one even when they are not
- explicitly declared in the class interface.
- </p>
- <p>
- In general then:
- </p>
- <ul>
- <li>
- If a C++ class does not declare any explicit constructor, SWIG will
- automatically generate a wrapper for one.
- </li>
- <li>
- If a C++ class does not declare an explicit copy constructor, SWIG will
- automatically generate a wrapper for one if the <tt>%copyctor</tt> is used.
- </li>
- <li>
- If a C++ class does not declare an explicit destructor, SWIG will
- automatically generate a wrapper for one.
- </li>
- </ul>
- <p>
- And as in C++, a few rules that alters the previous behavior:
- </p>
- <ul>
- <li>A default constructor is not created if a class already defines a constructor with arguments.
- </li>
- <li>Default constructors are not generated for classes with pure virtual methods or for classes that
- inherit from an abstract class, but don't provide definitions for all of the pure methods.
- </li>
- <li>A default constructor is not created unless all base classes support a
- default constructor.
- </li>
- <li>Default constructors and implicit destructors are not created if a class
- defines them in a <tt>private</tt> or <tt>protected</tt> section.
- </li>
- <li>Default constructors and implicit destructors are not created if any base
- class defines a non-public default constructor or destructor.
- </li>
- </ul>
- <p>
- SWIG should never generate a default constructor, copy constructor or
- default destructor wrapper for a class in which it is illegal to do so. In
- some cases, however, it could be necessary (if the complete class
- declaration is not visible from SWIG, and one of the above rules is
- violated) or desired (to reduce the size of the final interface) by
- manually disabling the implicit constructor/destructor generation.
- </p>
- <p>
- To manually disable these, the <tt>%nodefaultctor</tt> and <tt>%nodefaultdtor</tt>
- <a href="Customization.html#Customization_feature_flags">feature flag</a> directives
- can be used. Note that these directives only affects the
- implicit generation, and they have no effect if the default/copy
- constructors or destructor are explicitly declared in the class
- interface.
- </p>
- <p>
- For example:
- </p>
- <div class="code">
- <pre>
- %nodefaultctor Foo; // Disable the default constructor for class Foo.
- class Foo { // No default constructor is generated, unless one is declared
- ...
- };
- class Bar { // A default constructor is generated, if possible
- ...
- };
- </pre>
- </div>
- <p>
- The directive <tt>%nodefaultctor</tt> can also be applied "globally", as in:
- </p>
- <div class="code">
- <pre>
- %nodefaultctor; // Disable creation of default constructors
- class Foo { // No default constructor is generated, unless one is declared
- ...
- };
- class Bar {
- public:
- Bar(); // The default constructor is generated, since one is declared
- };
- %clearnodefaultctor; // Enable the creation of default constructors again
- </pre>
- </div>
- <p>
- The corresponding <tt>%nodefaultdtor</tt> directive can be used
- to disable the generation of the default or implicit destructor, if
- needed. Be aware, however, that this could lead to memory leaks in the
- target language. Hence, it is recommended to use this directive only
- in well known cases. For example:
- </p>
- <div class="code">
- <pre>
- %nodefaultdtor Foo; // Disable the implicit/default destructor for class Foo.
- class Foo { // No destructor is generated, unless one is declared
- ...
- };
- </pre>
- </div>
- <p>
- <b>Compatibility Note:</b> The generation of default
- constructors/implicit destructors was made the default behavior in SWIG
- 1.3.7. This may break certain older modules, but the old behavior can
- be easily restored using <tt>%nodefault</tt> or the
- <tt>-nodefault</tt> command line option. Furthermore, in order for
- SWIG to properly generate (or not generate) default constructors, it
- must be able to gather information from both the <tt>private</tt> and
- <tt>protected</tt> sections (specifically, it needs to know if a private or
- protected constructor/destructor is defined). In older versions of
- SWIG, it was fairly common to simply remove or comment out
- the private and protected sections of a class due to parser limitations.
- However, this removal may now cause SWIG to erroneously generate constructors
- for classes that define a constructor in those sections. Consider restoring
- those sections in the interface or using <tt>%nodefault</tt> to fix the problem.
- </p>
- <p>
- <b>Note:</b> The <tt>%nodefault</tt>
- directive/<tt>-nodefault</tt> options described above, which disable both the default
- constructor and the implicit destructors, could lead to memory
- leaks, and so it is strongly recommended to not use them.
- </p>
- <H3><a name="SWIGPlus_nn9"></a>6.6.3 When constructor wrappers aren't created</H3>
- <p>
- If a class defines a constructor, SWIG normally tries to generate a wrapper for it. However, SWIG will
- not generate a constructor wrapper if it thinks that it will result in illegal wrapper code. There are really
- two cases where this might show up.
- </p>
- <p>
- First, SWIG won't generate wrappers for protected or private constructors. For example:
- </p>
- <div class="code">
- <pre>
- class Foo {
- protected:
- Foo(); // Not wrapped.
- public:
- ...
- };
- </pre>
- </div>
- <p>
- Next, SWIG won't generate wrappers for a class if it appears to be abstract--that is, it has undefined
- pure virtual methods. Here are some examples:
- </p>
- <div class="code">
- <pre>
- class Bar {
- public:
- Bar(); // Not wrapped. Bar is abstract.
- virtual void spam(void) = 0;
- };
- class Grok : public Bar {
- public:
- Grok(); // Not wrapped. No implementation of abstract spam().
- };
- </pre>
- </div>
- <p>
- Some users are surprised (or confused) to find missing constructor wrappers in their interfaces. In almost
- all cases, this is caused when classes are determined to be abstract. To see if this is the case, run SWIG with
- all of its warnings turned on:
- </p>
- <div class="shell">
- <pre>
- % swig -Wall -python module.i
- </pre>
- </div>
- <p>
- In this mode, SWIG will issue a warning for all abstract classes. It is possible to force a class to be
- non-abstract using this:
- </p>
- <div class="code">
- <pre>
- %feature("notabstract") Foo;
- class Foo : public Bar {
- public:
- Foo(); // Generated no matter what---not abstract.
- ...
- };
- </pre>
- </div>
- <p>
- More information about <tt>%feature</tt> can be found in the <a href="Customization.html#Customization">Customization features</a> chapter.
- </p>
- <H3><a name="SWIGPlus_nn10"></a>6.6.4 Copy constructors</H3>
- <p>
- If a class defines more than one constructor, its behavior depends on the capabilities of the
- target language. If overloading is supported, the copy constructor is accessible using
- the normal constructor function. For example, if you have this:
- </p>
- <div class="code">
- <pre>
- class List {
- public:
- List();
- List(const List &); // Copy constructor
- ...
- };
- </pre>
- </div>
- <p>
- then the copy constructor can be used as follows:
- </p>
- <div class="targetlang">
- <pre>
- x = List() # Create a list
- y = List(x) # Copy list x
- </pre>
- </div>
- <p>
- If the target language does not support overloading, then the copy constructor is available
- through a special function like this:
- </p>
- <div class="code">
- <pre>
- List *copy_List(List *f) {
- return new List(*f);
- }
- </pre>
- </div>
- <p>
- <b>Note:</b> For a class <tt>X</tt>, SWIG only treats a constructor as
- a copy constructor if it can be applied to an object of type
- <tt>X</tt> or <tt>X *</tt>. If more than one copy constructor is
- defined, only the first definition that appears is used as the copy
- constructor--other definitions will result in a name-clash.
- Constructors such as <tt>X(const X &)</tt>, <tt>X(X &)</tt>, and
- <tt>X(X *)</tt> are handled as copy constructors in SWIG.
- </p>
- <p>
- <b>Note:</b> SWIG does <em>not</em> generate a copy constructor
- wrapper unless one is explicitly declared in the class. This differs
- from the treatment of default constructors and destructors.
- However, copy constructor wrappers can be generated if using the <tt>copyctor</tt>
- <a href="Customization.html#Customization_feature_flags">feature flag</a>. For example:
- </p>
- <div class="code">
- <pre>
- %copyctor List;
- class List {
- public:
- List();
- };
- </pre>
- </div>
- <p>
- Will generate a copy constructor wrapper for <tt>List</tt>.
- </p>
- <p>
- <b>Compatibility note:</b> Special support for copy constructors was
- not added until SWIG-1.3.12. In previous versions, copy constructors
- could be wrapped, but they had to be renamed. For example:
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- Foo();
- %name(CopyFoo) Foo(const Foo &);
- ...
- };
- </pre>
- </div>
- <p>
- For backwards compatibility, SWIG does not perform any special
- copy-constructor handling if the constructor has been manually
- renamed. For instance, in the above example, the name of the
- constructor is set to <tt>new_CopyFoo()</tt>. This is the same as in
- older versions.
- </p>
- <H3><a name="SWIGPlus_nn11"></a>6.6.5 Member functions</H3>
- <p>
- All member functions are roughly translated into accessor functions like this :</p>
- <div class="code"><pre>
- int List_search(List *obj, char *value) {
- return obj->search(value);
- }
- </pre></div>
- <p>
- This translation is the same even if the member function has been
- declared as <tt>virtual</tt>.
- </p>
- <p>
- It should be noted that SWIG does not <em>actually</em> create a C accessor
- function in the code it generates. Instead, member access such as
- <tt>obj->search(value)</tt> is directly inlined into the generated
- wrapper functions. However, the name and calling convention of the
- low-level procedural wrappers match the accessor function prototype described above.
- </p>
- <H3><a name="SWIGPlus_nn12"></a>6.6.6 Static members</H3>
- <p>
- Static member functions are called directly without making any special
- transformations. For example, the static member function
- <tt>print(List *l)</tt> directly invokes <tt>List::print(List *l)</tt>
- in the generated wrapper code.
- </p>
- <H3><a name="SWIGPlus_member_data"></a>6.6.7 Member data</H3>
- <p>
- Member data is handled in exactly the same manner as for C
- structures. A pair of accessor functions are effectively created. For example
- :</p>
- <div class="code"><pre>
- int List_length_get(List *obj) {
- return obj->length;
- }
- int List_length_set(List *obj, int value) {
- obj->length = value;
- return value;
- }
- </pre></div>
- <p>
- A read-only member can be created using the <tt>%immutable</tt> and <tt>%mutable</tt>
- <a href="Customization.html#Customization_feature_flags">feature flag</a> directive.
- For example, we probably wouldn't want
- the user to change the length of a list so we could do the following
- to make the value available, but read-only.</p>
- <div class="code"><pre>
- class List {
- public:
- ...
- %immutable;
- int length;
- %mutable;
- ...
- };
- </pre></div>
- <p>
- Alternatively, you can specify an immutable member in advance like this:
- </p>
- <div class="code">
- <pre>
- %immutable List::length;
- ...
- class List {
- ...
- int length; // Immutable by above directive
- ...
- };
- </pre>
- </div>
- <p>
- Similarly, all data attributes declared as <tt>const</tt> are wrapped as read-only members.
- </p>
- <p>
- There are some subtle issues when wrapping data members that are
- themselves classes. For instance, if you had another class like this,
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- List items;
- ...
- </pre>
- </div>
- <p>
- then the low-level accessor to the <tt>items</tt> member actually uses pointers. For example:
- </p>
- <div class="code">
- <pre>
- List *Foo_items_get(Foo *self) {
- return &self->items;
- }
- void Foo_items_set(Foo *self, List *value) {
- self->items = *value;
- }
- </pre>
- </div>
- <p>
- More information about this can be found in the SWIG Basics chapter,
- <a href="SWIG.html#SWIG_structure_data_members">Structure data members</a> section.
- </p>
- <p>
- The wrapper code to generate the accessors for classes comes from the pointer typemaps.
- This can be somewhat unnatural for some types.
- For example, a user would expect the STL std::string class member variables to be wrapped as a string in the target language,
- rather than a pointer to this class.
- The const reference typemaps offer this type of marshalling, so there is a feature to tell SWIG to use the const reference typemaps rather than the pointer typemaps.
- It is the <tt>%naturalvar</tt> directive and is used as follows:
- </p>
- <div class="code">
- <pre>
- // All List variables will use const List& typemaps
- %naturalvar List;
- // Only Foo::myList will use const List& typemaps
- %naturalvar Foo::myList;
- struct Foo {
- List myList;
- };
- // All variables will use const reference typemaps
- %naturalvar;
- </pre>
- </div>
- <p>
- The observant reader will notice that <tt>%naturalvar</tt> works like any other
- <a href="Customization.html#Customization_feature_flags">feature flag</a> directive,
- except it can also be attached to class types.
- The first of the example usages above show <tt>%naturalvar</tt> attaching to the <tt>List</tt> class.
- Effectively this feature changes the way accessors are generated to the following:
- </p>
- <div class="code">
- <pre>
- const List &Foo_items_get(Foo *self) {
- return self->items;
- }
- void Foo_items_set(Foo *self, const List &value) {
- self->items = value;
- }
- </pre>
- </div>
- <p>
- In fact it is generally a good idea to use this feature globally as the reference typemaps have extra NULL checking compared to the pointer typemaps.
- A pointer can be NULL, whereas a reference cannot, so the extra checking ensures that the target language user does not pass in a value that translates
- to a NULL pointer and thereby preventing any potential NULL pointer dereferences.
- The <tt>%naturalvar</tt> feature will apply to global variables in addition to member variables in some language modules, eg C# and Java.
- </p>
- <p>
- Other alternatives for turning this feature on globally are to use the <tt>swig -naturalvar</tt> commandline option
- or the module mode option, <tt>%module(naturalvar=1)</tt>
- </p>
- <p>
- <b>Compatibility note:</b> The <tt>%naturalvar</tt> feature was introduced in SWIG-1.3.28, prior to which it was necessary to manually apply the const reference
- typemaps, eg <tt>%apply const std::string & { std::string * }</tt>, but this example would also apply the typemaps to methods taking a <tt>std::string</tt> pointer.
- </p>
- <p>
- <b>Compatibility note:</b> Read-only access used to be controlled by a pair of directives
- <tt>%readonly</tt> and <tt>%readwrite</tt>. Although these directives still work, they
- generate a warning message. Simply change the directives to <tt>%immutable;</tt> and
- <tt>%mutable;</tt> to silence the warning. Don't forget the extra semicolon!
- </p>
- <p>
- <b>Compatibility note:</b> Prior to SWIG-1.3.12, all members of unknown type were
- wrapped into accessor functions using pointers. For example, if you had a structure
- like this
- </p>
- <div class="code">
- <pre>
- struct Foo {
- size_t len;
- };
- </pre>
- </div>
- <p>
- and nothing was known about <tt>size_t</tt>, then accessors would be
- written to work with <tt>size_t *</tt>. Starting in SWIG-1.3.12, this
- behavior has been modified. Specifically, pointers will <em>only</em>
- be used if SWIG knows that a datatype corresponds to a structure or
- class. Therefore, the above code would be wrapped into accessors
- involving <tt>size_t</tt>. This change is subtle, but it smooths over
- a few problems related to structure wrapping and some of SWIG's
- customization features.
- </p>
- <H2><a name="SWIGPlus_default_args"></a>6.7 Default arguments</H2>
- <p>
- SWIG will wrap all types of functions that have default arguments. For example member functions:
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- void bar(int x, int y = 3, int z = 4);
- };
- </pre>
- </div>
- <p>
- SWIG handles default arguments by generating an extra overloaded method for each defaulted argument.
- SWIG is effectively handling methods with default arguments as if it was wrapping the equivalent overloaded methods.
- Thus for the example above, it is as if we had instead given the following to SWIG:
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- void bar(int x, int y, int z);
- void bar(int x, int y);
- void bar(int x);
- };
- </pre>
- </div>
- <p>
- The wrappers produced are exactly the same as if the above code was instead fed into SWIG.
- Details of this are covered later in the <a href="#SWIGPlus_overloaded_methods">Wrapping Overloaded Functions and Methods</a> section.
- This approach allows SWIG to wrap all possible default arguments, but can be verbose.
- For example if a method has ten default arguments, then eleven wrapper methods are generated.
- </p>
- <p>
- Please see the <a href="Customization.html#Customization_features_default_args">Features and default arguments</a>
- section for more information on using <tt>%feature</tt> with functions with default arguments.
- The <a href="#ambiguity_resolution_renaming">Ambiguity resolution and renaming</a> section
- also deals with using <tt>%rename</tt> and <tt>%ignore</tt> on methods with default arguments.
- If you are writing your own typemaps for types used in methods with default arguments, you may also need to write a <tt>typecheck</tt> typemap.
- See the <a href="Typemaps.html#Typemaps_overloading">Typemaps and overloading</a> section for details or otherwise
- use the <tt>compactdefaultargs</tt> feature flag as mentioned below.
- </p>
- <p>
- <b>Compatibility note:</b> Versions of SWIG prior to SWIG-1.3.23 wrapped default arguments slightly differently.
- Instead a single wrapper method was generated and the default values were copied into the C++ wrappers
- so that the method being wrapped was then called with all the arguments specified.
- If the size of the wrappers are a concern then this approach to wrapping methods with default arguments
- can be re-activated by using the <tt>compactdefaultargs</tt>
- <a href="Customization.html#Customization_feature_flags">feature flag</a>.
- </p>
- <div class="code">
- <pre>
- %feature("compactdefaultargs") Foo::bar;
- class Foo {
- public:
- void bar(int x, int y = 3, int z = 4);
- };
- </pre>
- </div>
- <p>
- This is great for reducing the size of the wrappers, but the caveat is it does not work for the statically typed languages,
- such as C# and Java,
- which don't have optional arguments in the language,
- Another restriction of this feature is that it cannot handle default arguments that are not public.
- The following example illustrates this:
- </p>
- <div class="code">
- <pre>
- class Foo {
- private:
- static const int spam;
- public:
- void bar(int x, int y = spam); // Won't work with %feature("compactdefaultargs") -
- // private default value
- };
- </pre>
- </div>
- <p>
- This produces uncompileable wrapper code because default values in C++ are
- evaluated in the same scope as the member function whereas SWIG
- evaluates them in the scope of a wrapper function (meaning that the
- values have to be public).
- </p>
- <p>
- This feature is automatically turned on when wrapping <a href="SWIG.html#SWIG_default_args">C code with default arguments</a>
- and whenever keyword arguments (kwargs) are specified for either C or C++ code.
- Keyword arguments are a language feature of some scripting languages, for example Ruby and Python.
- SWIG is unable to support kwargs when wrapping overloaded methods, so the default approach cannot be used.
- </p>
- <H2><a name="SWIGPlus_nn15"></a>6.8 Protection</H2>
- <p>
- SWIG wraps class members that are public following the C++
- conventions, i.e., by explicit public declaration or by the use of
- the <tt> using</tt> directive. In general, anything specified in a
- private or protected section will be ignored, although the internal
- code generator sometimes looks at the contents of the private and
- protected sections so that it can properly generate code for default
- constructors and destructors. Directors could also modify the way
- non-public virtual protected members are treated.
- </p>
- <p>
- By default, members of a class definition are assumed to be private
- until you explicitly give a `<tt>public:</tt>' declaration (This is
- the same convention used by C++).
- </p>
- <H2><a name="SWIGPlus_nn16"></a>6.9 Enums and constants</H2>
- <p>
- Enumerations and constants are handled differently by the different language modules and are described in detail in the appropriate language chapter.
- However, many languages map enums and constants in a class definition
- into constants with the classname as a prefix. For example :</p>
- <div class="code"><pre>
- class Swig {
- public:
- enum {ALE, LAGER, PORTER, STOUT};
- };
- </pre></div>
- <p>
- Generates the following set of constants in the target scripting language :</p>
- <div class="targetlang"><pre>
- Swig_ALE = Swig::ALE
- Swig_LAGER = Swig::LAGER
- Swig_PORTER = Swig::PORTER
- Swig_STOUT = Swig::STOUT
- </pre></div>
- <p>
- Members declared as <tt>const</tt> are wrapped as read-only members and do not create constants.
- </p>
- <H2><a name="SWIGPlus_nn17"></a>6.10 Friends</H2>
- <p>
- Friend declarations are recognised by SWIG. For example, if
- you have this code:
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- ...
- friend void blah(Foo *f);
- ...
- };
- </pre>
- </div>
- <p>
- then the <tt>friend</tt> declaration does result in a wrapper code
- equivalent to one generated for the following declaration
- </p>
- <div class="code">
- <pre>
- class Foo {
- public:
- ...
- };
- void blah(Foo *f);
- </pre>
- </div>
- <p>
- A friend declaration, as in C++, is understood to be in the same scope
- where the class is declared, hence, you can have
- </p>
- <div class="code">
- <pre>
- %ignore bar::blah(Foo *f);
- namespace bar {
- class Foo {
- public:
- ...
- friend void blah(Foo *f);
- ...
- };
- }
- </pre>
- </div>
- <p>
- and a wrapper for the method 'blah' will not be generated.
- </p>
- <H2><a name="SWIGPlus_nn18"></a>6.11 References and pointers</H2>
- <p>
- C++ references are supported, but SWIG transforms them back into pointers. For example,
- a declaration like this :</p>
- <div class="code"><pre>
- class Foo {
- public:
- double bar(double &a);
- }
- </pre></div>
- <p>
- has a low-level accessor
- </p>
- <div class="code"><pre>
- double Foo_bar(Foo *obj, double *a) {
- obj->bar(*a);
- }
- </pre></div>
- <p>
- As a special case, most language modules pass <tt>const</tt> references to primitive datatypes (<tt>int</tt>, <tt>short</tt>,
- <tt>float</tt>, etc.) by value instead of pointers. For example, if you have a function like this,
- </p>
- <div class="code">
- <pre>
- void foo(const int &x);
- </pre>
- </div>
- <p>
- it is called from a script as follows:
- </p>
- <div class="targetlang">
- <pre>
- foo(3) # Notice pass by value
- </pre>
- </div>
- <p>
- Functions that return a reference are remapped to return a pointer instead.
- For example:
- </p>
- <div class="code"><pre>
- class Bar {
- public:
- Foo &spam();
- };
- </pre>
- </div>
- <p>
- Generates an accessor like this:
- </p>
- <div class="code">
- <pre>
- Foo *Bar_spam(Bar *obj) {
- Foo &result = obj->spam();
- return &result;
- }
- </pre>
- </div>
- <p>
- However, functions that return <tt>const</tt> references to primitive datatypes (<tt>int</tt>, <tt>short</tt>, etc.) normally
- return the result as a value rather than a pointer. For example, a function like this,
- </p>
- <div class="code">
- <pre>
- const int &bar();
- </pre>
- </div>
- <p>
- will return integers such as 37 or 42 in the target scripting language rather than a pointer to an integer.
- </p>
- <P>
- Don't return references to objects allocated as local variables on the
- stack. SWIG doesn't make a copy of the objects so this will probably
- cause your program to crash.
- <p>
- <b>Note:</b> The special treatment for references to primitive datatypes is necessary to provide
- more seamless integration with more advanced C++ wrapping applications---especially related to
- templates and the STL. This was first added in SWIG-1.3.12.
- </p>
- <H2><a name="SWIGPlus_nn19"></a>6.12 Pass and return by value</H2>
- <p>
- Occasionally, a C++ program will pass and return class objects by value. For example, a function
- like this might appear:
- </p>
- <div class="code">
- <pre>
- Vector cross_product(Vector a, Vector b);
- </pre>
- </div>
- <p>
- If no information is supplied about <tt>Vector</tt>, SWIG creates a wrapper function similar to the
- following:
- </p>
- <div class="code">
- <pre>
- Vector *wrap_cross_product(Vector *a, Vector *b) {
- Vector x = *a;
- Vector y = *b;
- Vector r = cross_product(x,y);
- return new Vector(r);
- }</pre>
- </div>
- <p>
- In order for the wrapper code to compile, <tt>Vector</tt> must define a copy constructor and a
- default constructor.
- </p>
- <p>
- If <tt>Vector</tt> is defined as a class in the interface, but it does not
- support a default constructor, SWIG changes the wrapper code by encapsulating
- the arguments inside a special C++ template wrapper class, through a process
- called the "Fulton Transform". This produces a wrapper that looks like this:
- </p>
- <div class="code">
- <pre>
- Vector cross_product(Vector *a, Vector *b) {
- SwigValueWrapper<Vector> x = *a;
- SwigValueWrapper<Vector> y = *b;
- SwigValueWrapper<Vector> r = cross_product(x,y);
- return new Vector(r);
- }
- </pre>
- </div>
- <p>
- This transformation is a little sneaky, but it provides support for
- pass-by-value even when a class does not provide a default constructor
- and it makes it possible to properly support a number of SWIG's
- customization options. The definition of <tt>SwigValueWrapper</tt>
- can be found by reading the SWIG wrapper code. This class is really nothing more than a thin
- wrapper around a pointer.
- </p>
- <p>
- Although SWIG usually detects the classes to which the Fulton Transform should
- be applied, in some situations it's necessary to override it. That's done with
- <tt>%feature("valuewrapper")</tt> to ensure it is used and <tt>%feature("novaluewrapper")</tt>
- to ensure it is not used:
- </p>
- <div class="code"><pre>
- %feature("novaluewrapper") A;
- class A;
- %feature("valuewrapper") B;
- struct B {
- B();
- // ....
- };
- </pre></div>
- <p>
- It is well worth considering turning this feature on for classes that do have a default constructor.
- It will remove a redundant constructor call at the point of the variable declaration in the wrapper,
- so will generate notably better performance for large objects or for classes with expensive construction.
- Alternatively consider returning a reference or a pointer.
- </p>
- <p>
- <b>Note:</b> this transformation has no effect on typemaps
- or any other part of SWIG---it should be transparent except that you
- may see this code when reading the SWIG output file.
- </p>
- <p>
- <b>
- Note: </b>This template transformation is new in SWIG-1.3.11 and may be refined in
- future SWIG releases. In practice, it is only absolutely necessary to do this for
- classes that don't define a default constructor.
- </p>
- <p>
- <b>Note:</b> The use of this template only occurs when objects are passed or returned by value.
- It is not used for C++ pointers or references.
- </p>
- <H2><a name="SWIGPlus_nn20"></a>6.13 Inheritance</H2>
- <p>
- SWIG supports C++ inheritance of classes and allows both single and
- multiple inheritance, as limited or allowed by the target
- language. The SWIG type-checker knows about the relationship between
- base and derived classes and allows pointers to any object of a
- derived class to be used in functions of a base class. The
- type-checker properly casts pointer values and is safe to use with
- multiple inheritance.
- </p>
- <p> SWIG treats private or protected inheritance as close to the C++
- spirit, and target language capabilities, as possible. In most
- cases, this means that SWIG will parse the non-public inheritance
- declarations, but that will have no effect in the generated code,
- besides the implicit policies derived for constructor and
- destructors.
- </p>
- <p>
- The following example shows how SWIG handles inheritance. For clarity,
- the full C++ code has been omitted.</p>
- <div class="code"><pre>
- // shapes.i
- %module shapes
- %{
- #include "shapes.h"
- %}
- class Shape {
- public:
- double x,y;
- virtual double area() = 0;
- virtual double perimeter() = 0;
- void set_location(double x, double y);
- };
- class Circle : public Shape {
- public:
- Circle(double radius);
- ~Circle();
- double area();
- double perimeter();
- };
- class Square : public Shape {
- public:
- Square(double size);
- ~Square();
- double area();
- double perimeter();
- }
- </pre></div>
- <p>
- When wrapped into Python, we can perform the following operations (shown using the low level Python accessors):
- </p>
- <div class="targetlang"><pre>
- $ python
- >>> import shapes
- >>> circle = shapes.new_Circle(7)
- >>> square = shapes.new_Square(10)
- >>> print shapes.Circle_area(circle)
- 153.93804004599999757
- >>> print shapes.Shape_area(circle)
- 153.93804004599999757
- >>> print shapes.Shape_area(square)
- 100.00000000000000000
- >>> shapes.Shape_set_location(square,2,-3)
- >>> print shapes.Shape_perimeter(square)
- 40.00000000000000000
- >>>
- </pre></div>
- <p>
- In this example, Circle and Square objects have been created. Member
- functions can be invoked on each object by making calls to
- <tt>Circle_area</tt>, <tt>Square_area</tt>, and so on. However, the same
- results can be accomplished by simply using the <tt>Shape_area</tt>
- function on either object.
- </p>
- <p>
- One important point concerning inheritance is that the low-level
- accessor functions are only generated for classes in which they are
- actually declared. For instance, in the above example, the method
- <tt>set_location()</tt> is only accessible as
- <tt>Shape_set_location()</tt> and not as
- <tt>Circle_set_location()</tt> or <tt>Square_set_location()</tt>. Of
- course, the <tt>Shape_set_location()</tt> function will accept any
- kind of object derived from Shape. Similarly, accessor functions for
- the attributes <tt>x</tt> and <tt>y</tt> are generated as
- <tt>Shape_x_get()</tt>, <tt>Shape_x_set()</tt>,
- <tt>Shape_y_get()</tt>, and <tt>Shape_y_set()</tt>. Functions such as
- <tt>Circle_x_get()</tt> are not available--instead you should use
- <tt>Shape_x_get()</tt>.
- </p>
- <p>
- Note that there is a one to one correlation between the low-level accessor functions and
- the proxy methods and therefore there is also a one to one correlation between
- the C++ class methods and the generated proxy class methods.
- </p>
- <p>
- <b>Note:</b> For the best results, SWIG requires all
- base classes to be defined in an interface. Otherwise, you may get a
- warning message like this:
- </p>
- <div class="shell">
- <pre>
- example.i:18: Warning(401): Nothing known about base class 'Foo'. Ignored.
- </pre>
- </div>
- <p>
- If any base class is undefined, SWIG still generates correct type
- relationships. For instance, a function accepting a <tt>Foo *</tt>
- will accept any object derived from <tt>Foo</tt> regardless of whether
- or not SWIG actually wrapped the <tt>Foo</tt> class. If you really
- don't want to generate wrappers for the base class, but you want to
- silence the warning, you might consider using the <tt>%import</tt>
- directive to include the file that defines <tt>Foo</tt>.
- <tt>%import</tt> simply gathers type information, but doesn't generate
- wrappers. Alternatively, you could just define <tt>Foo</tt> as an empty class
- in the SWIG interface or use
- <a href="Warnings.html#Warnings_suppression">warning suppression</a>.
- </p>
- <p>
- <b>Note:</b> <tt>typedef</tt>-names <em>can</em> be used as base classes. For example:
- </p>
- <div class="code">
- <pre>
- class Foo {
- ...
- };
- typedef Foo FooObj;
- class Bar : public FooObj { // Ok. Base class is Foo
- ...
- };
- </pre>
- </div>
- <p>
- Similarly, <tt>typedef</tt> allows unnamed structures to be used as base classes. For example:
- </p>
- <div class="code">
- <pre>
- typedef struct {
- ...
- } Foo;
- class Bar : public Foo { // Ok.
- ...
- };
- </pre>
- </div>
- <p>
- <b>Compatibility Note:</b> Starting in version 1.3.7, SWIG only
- generates low-level accessor wrappers for the declarations that are
- actually defined in each class. This differs from SWIG1.1 which used
- to inherit all of the declarations defined in base classes and
- regenerate specialized accessor functions such as
- <tt>Circle_x_get()</tt>, <tt>Square_x_get()</tt>,
- <tt>Circle_set_location()</tt>, and <tt>Square_set_location()</tt>.
- This behavior resulted in huge amounts of replicated code for large
- class hierarchies and made it awkward to build applications spread
- across multiple mo…
Large files files are truncated, but you can click here to view the full file