1/* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4 *
5 * attribute.swg
6 *
7 * Attribute implementation
8 * ----------------------------------------------------------------------------- */
9
10/*
11  The following macros convert a pair of set/get methods
12  into a "native" attribute.
13
14  Use %attribute when you have a pair of get/set methods to a primitive type
15  like in:
16
17      %attribute(A, int, a, get_a, set_a);
18
19      struct A
20      {
21        int get_a() const;
22        void set_a(int aa);
23      };
24
25  If you don't provide a 'set' method, a 'read-only' attribute
26  is generated, ie, like in:
27
28      %attribute(A, int, c, get_c);
29
30  Use %attributeref when you have const/non-const reference access methods
31  for primitive types or class/structs, like in:
32
33      %attributeref(A, int, b);
34
35      struct A
36      {
37        const int& b() const;
38        int& b();
39      };
40
41      %attributeref(B, int, c);
42
43      struct B
44      {
45        int& c();
46      };
47
48  You can also use
49
50      %attributeref(Class, AttributeType, AttributeName, AccessorMethod)
51
52  if the internal C++ reference methods have a different name from the
53  attribute you want, so
54
55      %attributeref(B, int, d, c);
56
57  is the same as the last example, but instead of the attribute 'c' being
58  called 'c', it is called 'd'.
59
60  Now you can use the attributes like so:
61
62      x = A()
63      x.a = 3        # calls A::set_a
64      print x.a      # calls A::get_a
65
66      x.b = 3        # calls A::b()
67      print x.b      # calls A::b() const
68
69  Use %attribute2 instead of %attribute to indicate that reference-pointer
70  translation is required. You use %attribute2 instead of %attribute in
71  cases like this:
72
73  %attribute2(MyClass, MyFoo, Foo, GetFoo, SetFoo);
74  %inline %{
75    struct MyFoo {
76      int x;
77    };
78    class MyClass {
79      MyFoo foo;
80    public:
81      MyFoo& GetFoo() { return foo; }
82      void SetFoo(const MyFoo& other) { foo = other; }
83    };
84  %}
85
86  Here, the data type of the property is a wrapped type (MyFoo) and on the
87  C++ side it is passed by reference. The problem is that the SWIG wrapper will
88  pass around a pointer (MyFoo *) which is not compatible with the reference
89  type of the accessors (MyFoo &). Therefore, if you use %attribute, you'll get
90  an error from your C/C++ compiler. %attribute2 translates between a pointer
91  and a reference to eliminate the error. In case you're confused, let's make it
92  simple: just use %attribute at first, but if the C/C++ compiler gives an error
93  while compiling the wrapper, try %attribute2 instead.
94
95  NOTE: remember that if the type contains commas, such as 'std::pair<int,int>',
96  you need to use the macro like:
97
98  %attributeref(A, %arg(std::pair<int,int>), pval);
99
100  where %arg() 'normalizes' the type to be understood as a single
101  argument, otherwise the macro will get confused by the comma.
102
103  The %attributeval is the same as %attribute, but should be used when the type
104  is a class/struct (ie a non-primitive type) and when the get and set methods
105  return/pass by value. The following is very similar to the above example, but
106  note that the access is by value rather than reference.
107
108    %attributeval(MyClassVal, MyFoo, ReadWriteFoo, GetFoo, SetFoo);
109    %attributeval(MyClassVal, MyFoo, ReadOnlyFoo, GetFoo);
110    %inline %{
111      class MyClassVal {
112	MyFoo foo;
113      public:
114	MyFoo GetFoo() { return foo; }
115	void SetFoo(MyFoo other) { foo = other; }
116      };
117    %}
118
119  The %attributestring is the same as %attributeval, but should be used for string
120  class types, which are unusual as they are a class on the C++ side, but normally an
121  immutable/primitive type in the target language. Example usage for std::string:
122
123    %include <std_string.i>
124    %attributestring(MyStringyClass, std::string, ReadWriteString, GetString, SetString);
125    %attributestring(MyStringyClass, std::string, ReadOnlyString, GetString);
126    %inline %{
127      class MyStringyClass {
128	std::string str;
129      public:
130	MyStringyClass(const std::string &val) : str(val) {}
131	std::string GetString() { return str; }
132	void SetString(std::string other) { str = other; }
133      };
134    %}
135
136*/
137
138//
139// Define SWIG_ATTRIBUTE_TEMPLATE if you want to use templates instead of macros for the C++ get and set wrapper methods
140// Does not always generate compileable code, use at your peril!
141//
142//#define SWIG_ATTRIBUTE_TEMPLATE
143
144%define %attribute_custom(Class, AttributeType, AttributeName, GetMethod, SetMethod, GetMethodCall, SetMethodCall)
145  %ignore Class::GetMethod();
146  %ignore Class::GetMethod() const;
147  #if #SetMethod != #AttributeName
148    %ignore Class::SetMethod;
149  #endif
150  %extend Class {
151    AttributeType AttributeName;
152  }
153#if defined(__cplusplus) && defined(SWIG_ATTRIBUTE_TEMPLATE)
154  %{
155    template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(const C* self_) {
156      return GetMethodCall;
157    }
158    template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(C* self_) {
159      return GetMethodCall;
160    }
161    template < class C > inline void %mangle(Class) ##_## AttributeName ## _set(C* self_, AttributeType val_) {
162      SetMethodCall;
163    }
164  %}
165#else
166  %{
167    #define %mangle(Class) ##_## AttributeName ## _get(self_) GetMethodCall
168    #define %mangle(Class) ##_## AttributeName ## _set(self_, val_) SetMethodCall
169  %}
170#endif
171%enddef
172
173%define %attribute_readonly(Class, AttributeType, AttributeName, GetMethod, GetMethodCall)
174  %ignore Class::GetMethod();
175  %ignore Class::GetMethod() const;
176  %immutable Class::AttributeName;
177  %extend Class {
178    AttributeType AttributeName;
179  }
180#if defined(__cplusplus) && defined(SWIG_ATTRIBUTE_TEMPLATE)
181  %{
182    template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(const C* self_) {
183      return GetMethodCall;
184    }
185    template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(C* self_) {
186      return GetMethodCall;
187    }
188  %}
189#else
190  %{
191    #define %mangle(Class) ##_## AttributeName ## _get(self_) GetMethodCall
192  %}
193#endif
194%enddef
195
196
197// User macros
198
199%define %attribute(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
200  #if #SetMethod != ""
201    %attribute_custom(Class, AttributeType, AttributeName, GetMethod, SetMethod, self_->GetMethod(), self_->SetMethod(val_))
202  #else
203    %attribute_readonly(Class, AttributeType, AttributeName, GetMethod, self_->GetMethod())
204  #endif
205%enddef
206
207%define %attribute2(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
208  #if #SetMethod != ""
209    %attribute_custom(Class, AttributeType, AttributeName, GetMethod, SetMethod, &self_->GetMethod(), self_->SetMethod(*val_))
210  #else
211    %attribute_readonly(Class, AttributeType, AttributeName, GetMethod, &self_->GetMethod())
212  #endif
213%enddef
214
215%define %attributeref(Class, AttributeType, AttributeName, AccessorMethod...)
216  #if #AccessorMethod != ""
217    %attribute_custom(Class, AttributeType, AttributeName, AccessorMethod, AccessorMethod, self_->AccessorMethod(), self_->AccessorMethod() = val_)
218  #else
219    %attribute_custom(Class, AttributeType, AttributeName, AttributeName, AttributeName, self_->AttributeName(), self_->AttributeName() = val_)
220  #endif
221%enddef
222
223%define %attribute2ref(Class, AttributeType, AttributeName, AccessorMethod...)
224  #if #AccessorMethod != ""
225    %attribute_custom(Class, AttributeType, AttributeName, AccessorMethod, AccessorMethod, &self_->AccessorMethod(), self_->AccessorMethod() = *val_)
226  #else
227    %attribute_custom(Class, AttributeType, AccessorMethod, AccessorMethod, AccessorMethod, &self_->AccessorMethod(), self_->AccessorMethod() = *val_)
228  #endif
229%enddef
230
231// deprecated (same as %attributeref, but there is an argument order inconsistency)
232%define %attribute_ref(Class, AttributeType, AccessorMethod, AttributeName...)
233  #if #AttributeName != ""
234    %attribute_custom(Class, AttributeType, AttributeName, AccessorMethod, AccessorMethod, self_->AccessorMethod(), self_->AccessorMethod() = val_)
235  #else
236    %attribute_custom(Class, AttributeType, AccessorMethod, AccessorMethod, AccessorMethod, self_->AccessorMethod(), self_->AccessorMethod() = val_)
237  #endif
238%enddef
239
240
241%define %attributeval(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
242  %{
243    #define %mangle(Class) ##_## AttributeName ## _get(self_) new AttributeType(self_->GetMethod())
244  %}
245  #if #SetMethod != ""
246    %{
247      #define %mangle(Class) ##_## AttributeName ## _set(self_, val_) self_->SetMethod(*val_)
248    %}
249    #if #SetMethod != #AttributeName
250      %ignore Class::SetMethod;
251    #endif
252  #else
253    %immutable Class::AttributeName;
254  #endif
255  %ignore Class::GetMethod();
256  %ignore Class::GetMethod() const;
257  %newobject Class::AttributeName;
258  %extend Class {
259    AttributeType AttributeName;
260  }
261%enddef
262
263
264%define %attributestring(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
265  %{
266    #define %mangle(Class) ##_## AttributeName ## _get(self_) *new AttributeType(self_->GetMethod())
267  %}
268  #if #SetMethod != ""
269    %{
270      #define %mangle(Class) ##_## AttributeName ## _set(self_, val_) self_->SetMethod(val_)
271    %}
272    #if #SetMethod != #AttributeName
273      %ignore Class::SetMethod;
274    #endif
275  #else
276    %immutable Class::AttributeName;
277  #endif
278  %ignore Class::GetMethod();
279  %ignore Class::GetMethod() const;
280  %newobject Class::AttributeName;
281  %typemap(newfree) const AttributeType &AttributeName "delete $1;// my newfree override"
282  %extend Class {
283    AttributeType AttributeName;
284  }
285%enddef
286
287