15 February 2010

Easy Python generators using SWIG

In my research code, I have a number of classes that act as wrappers for containers, and they provide begin and end functions. I want an easy way to provide a generator for looping over these embedded containers. Because of the way SWIG's STL wrappers work, it's not (easily?) possible to wrap a vector of pointers, and we'd like to avoid all the extra overhead those wrappers have anyway: all we need is a way to increment a pointer and to tell if it's at the end.

So, my solution is to create a thin wrapper for only the increment operator ++, and extend the class with a function to return the "beginning" iterator and to check whether the iterator is at the end position.

For this particular instance, I have a class Mesh that has methods for beginLeftBoundaryFaces and endLeftBoundaryFaces—which return STL vector iterators that point to a Face *.

%inline %{
//! Thin wrapper for ONLY the increment operator
void _bfiter_incr( std::vector<Face *>::const_iterator* iter )
{
    // increment the iterator
    ++(*iter);
}
%}

%extend Mesh {
%insert("python") %{
    def left_boundary_faces(self):
        "A generator to iterate through boundary faces."
        faceIter = self._beginLeftBoundaryFaces()
        keepLooping = True
        while keepLooping == True:
            face = self._bfiter_dereference_Left( faceIter )
            if face:
                _bfiter_incr( faceIter )
                yield face
            else:
                keepLooping = False
%}

//! get the first element in the vector
std::vector<Face *>::const_iterator* _beginLeftBoundaryFaces()
{
    return new std::vector<Face *>::const_iterator(
            ($self->beginLeftBoundaryFaces()) );
}

//! dereference the iterator; return NULL if at the end
const Face* _bfiter_dereference_Left(
        const std::vector<Face *>::const_iterator* iter )
{
    // if at the end, return NULL
    if (*iter == ($self)->endLeftBoundaryFaces() ) {
        return NULL;
    }
    // otherwise, return the face to which this iterator points
    return **iter;
}
}

So now I can do:

for f in mesh.left_boundary_faces():
    print f.area()

or, of course, anything else now that I'm using Python.

See further updates on the thin Python wrappers for C++ iterators.

12 comments:

Anonymous said...

Hi Seth,

I came across this blogpost while looking for ways to access C++ STL:vector elements from python through SWIG. I used your sample code to create a .i file for my project. In my case, 'left_maps' replaces 'left_boundary_faces'.

When I try to do 'for f in left_maps: print "me" ' in python, I get "NameError: global name 'left_maps' is not defined". Any ideas on how to resolve this?

-Matt

Seth said...

Hey Matt,
Good catch, this was an error on my part. `left_boundary_faces` is a method of the class `Mesh` that is actually a generator, so I should have said `mesh.left_boundary_faces()`.

However, rather than using this code for an STL vector, you might consider using SWIG's built-in implementation with `%include `.

Anonymous said...

Hi Seth,

I appreciate the quick response. After putting in your fix, I get "Attribute Error: 'MapSet' has no attribute 'left_maps' ". ('MapSet' is analogous to 'Mesh' in your example)

Also, could you elaborate on what you said about using the built-in implementation using '%include' or give me a pointer to some documentation on it? My understanding after reading your post was that there is no easy way wrap STL:vectors in SWIG.

Thanks.
-Matt

Seth said...

Matt:

Sorry, the `%include <std_vector.i>` got eaten by the HTML parser. Take a look at the SWIG documentation. I only meant that wrapping arbitrary iterators was difficult; wrapping the built-in STL classes is easy with SWIG's functionality. If this doesn't answer your question, perhaps you could email me your code and some explanation. My email link is under the "About me" section.

Unknown said...

Nice Post. Keep sharing more and more SEO Training
Java Training
python Training
Salesforce Training
Tableau Training
AWS training
Dot Net Training
DevOps Training
Selenium Training

cihofurko said...

kayseriescortu.com - alacam.org - xescortun.com

Anonymous said...

Smm panel
Smm panel
iş ilanları
instagram takipçi satın al
hirdavatciburada.com
beyazesyateknikservisi.com.tr
servis
tiktok jeton hilesi

Anonymous said...

en son çıkan perde modelleri
nft nasıl alınır
lisans satın al
en son çıkan perde modelleri
uc satın al
yurtdışı kargo
özel ambulans
minecraft premium

sportsbet said...

Good content. You write beautiful things.
korsan taksi
mrbahis
sportsbet
vbet
vbet
taksi
mrbahis
hacklink
hacklink

bonus veren siteler said...

Good text Write good content success. Thank you
kralbet
tipobet
betmatik
kibris bahis siteleri
slot siteleri
betpark
poker siteleri
mobil ödeme bahis

Blck Luxury car said...

Renting a car is usually a less-than-exciting experience when traveling. Getting the keys to a bland four door is nothing to write home about. What many do not realize is that any vacation or business trip can be an adventure with a car hire. Luxury Car Rental Ahmedabad

Car rental services Ahmedabad

didem said...

mecidiyeköy
sakarya
istanbul
kayseri
ordu

XWF

Post a Comment