Home | History | Annotate | Download | only in typemaps
      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