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