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