Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Ooh, this is tricky (and fun). SWIG <em>doesn't</em> recognize this as an opportunity to generate @property: I imagine it'd be all too easy to slip up and recognize lots of false positives if it weren't done really carefully. However, since SWIG won't do it in generating C++, it's still entirely possible to do this in Python using a small metaclass.</p> <p>So, below, let's say we have a Math class that lets us set and get an integer variable named "pi". Then we can use this code:</p> <h2>example.h</h2> <pre><code>#ifndef EXAMPLE_H #define EXAMPLE_H class Math { public: int pi() const { return this-&gt;_pi; } void pi(int pi) { this-&gt;_pi = pi; } private: int _pi; }; #endif </code></pre> <h2>example.i</h2> <pre><code>%module example %{ #define SWIG_FILE_WITH_INIT #include "example.h" %} [essentially example.h repeated again] </code></pre> <h2>example.cpp</h2> <pre><code>#include "example.h" </code></pre> <h2>util.py</h2> <pre><code>class PropertyVoodoo(type): """A metaclass. Initializes when the *class* is initialized, not the object. Therefore, we are free to muck around the class methods and, specifically, descriptors.""" def __init__(cls, *a): # OK, so the list of C++ properties using the style described # in the OP is stored in a __properties__ magic variable on # the class. for prop in cls.__properties__: # Get accessor. def fget(self): # Get the SWIG class using super. We have to use super # because the only information we're working off of is # the class object itself (cls). This is not the most # robust way of doing things but works when the SWIG # class is the only superclass. s = super(cls, self) # Now get the C++ method and call its operator(). return getattr(s, prop)() # Set accessor. def fset(self, value): # Same as above. s = super(cls, self) # Call its overloaded operator(int value) to set it. return getattr(s, prop)(value) # Properties in Python are descriptors, which are in turn # static variables on the class. So, here we create the # static variable and set it to the property. setattr(cls, prop, property(fget=fget, fset=fset)) # type() needs the additional arguments we didn't use to do # inheritance. (Parent classes are passed in as arguments as # part of the metaclass protocol.) Usually a = [&lt;some swig # class&gt;] right now. super(PropertyVoodoo, cls).__init__(*a) # One more piece of work: SWIG selfishly overrides # __setattr__. Normal Python classes use object.__setattr__, # so that's what we use here. It's not really important whose # __setattr__ we use as long as we skip the SWIG class in the # inheritance chain because SWIG's __setattr__ will skip the # property we just created. def __setattr__(self, name, value): # Only do this for the properties listed. if name in cls.__properties__: object.__setattr__(self, name, value) else: # Same as above. s = super(cls, self) s.__setattr__(name, value) # Note that __setattr__ is supposed to be an instance method, # hence the self. Simply assigning it to the class attribute # will ensure it's an instance method; that is, it will *not* # turn into a static/classmethod magically. cls.__setattr__ = __setattr__ </code></pre> <h2>somefile.py</h2> <pre><code>import example from util import PropertyVoodoo class Math(example.Math): __properties__ = ['pi'] __metaclass__ = PropertyVoodoo m = Math() print m.pi m.pi = 1024 print m.pi m.pi = 10000 print m.pi </code></pre> <p>So the end result is just that you have to create a wrapper class for every SWIG Python class and then type two lines: one to mark which methods should be converted in properties and one to bring in the metaclass.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload