Wrapping C++ Library in Python, handling custom types
Question: i'm currently writing a NLP application in python which requires a fast POS
tagging implementation. the tagger has a c++ wrapper interface:

    
    
    #include "POSTagger.h"
    
    extern "C" POSTagger* initTagger(const char* fileName, bool Normalize, 
                                     double BeamThreshold, bool SentStartHeuristic,
                                     int MaxBeamSize)
    {
        FILE *file = open_file(fileName, "rb");
        POSTagger* tagger = new POSTagger(file, Normalize, BeamThreshold, 
                                          SentStartHeuristic, MaxBeamSize);
        fclose(file);
        return tagger;
    }
    
    
    extern "C" void getTags(POSTagger* tagger, char** words, int sentLen, 
                            char** tags)
    {
        Sentence sent(words, sentLen);
        tagger->annotate(sent);
    
        for( size_t i=0; i<sent.token.size(); i++ )
            tags[i] = strdup(tagger->tagmap.name(sent.token[i].tag));
    }
    
    
    extern "C" void destroyTagger(POSTagger* tagger) {
        delete tagger;
    }
    

i've never written a wrapper for c++ in python yet. so there are a couple of
questions:

  1. Can i store a custom C++ class instance in python? i've never seen that before. all examples that i did go through returned only basic data types. (this pos tagger has to be initialized with a language set, which requires some time to load it into the memory. therefore it is essential to only init and store it rather than rewriting the wrapper to create one for every tagging procedure and just return a tagged string)

  2. If 1 is possible: what is the easiest way? 


Answer: I'd suggest to use _Cython_ for this purpose. Writing C/C++ extension-types is
straight forward.

Unfortunately, I can't garuantee this code to be fully correct as I can't test
it without the header you use. # coding: utf-8 # file: postagger.pyx

    
    
    cimport libc.stdlib     as stdlib
    
    cdef extern from "Python.h":
        char* PyString_AsString(object)
    
    cdef extern from "yourPOSTagger.c":
    
        # note the syntax, to Cython the POSTagger class will be available
        # as cPOSTagger using this construct
        cppclass cPOSTagger "POSTagger":
            # we only need the POSTagger type to be available to cython
            # but no attributes, so we leave to ``pass``
            pass
    
        cPOSTagger* initTagger(char*, bint, double, bint, int)
        void        getTags(cPOSTagger*, char**, int, char**)
        void        destroyTagger(cPOSTagger*)
    
    cdef class POSTagger:
        """ Wraps the POSTagger.h ``POSTagger`` class. """
    
        cdef cPOSTagger*    tagger
    
        def __init__(self, char* fileName, bint Normalize, double BeamTreshold,
                           bint SentStartHeuristic, int MaxBeamSize):
            self.tagger = initTagger( fileName, Normalize, BeamTreshold,
                                      SentStartHeuristic, MaxBeamSize )
            if self.tagger == NULL:
                raise MemoryError()
    
        def __del__(self):
            destroyTagger(self.tagger)
    
        def getTags(self, tuple words, int sentLen):
            if not words:
                raise ValueError("'words' can not be None.")
    
            cdef char** _words = <char**> stdlib.malloc(sizeof(char*) * len(words))
            cdef int    i      = 0
            for item in words:
                if not isinstance(item, basestring):
                    stdlib.free(_words)
                    raise TypeError( "Element in tuple 'words' must be of type "
                                     "``basestring``." )
                _words[i] = PyString_AsString(item)
                i += 1
    
            cdef int nTags   = len(words)   # Really? Dunno..
            cdef char** tags = <char**> stdlib.malloc(sizeof(char*) * len(words))
    
            getTags(self.tagger, _words, sentLen, tags)
    
            cdef list reval = []
            cdef str  temp
            for 0 <= i < nTags:
                temp = tags[i]
                reval.append(temp)
                stdlib.free(tags[i])
    
            stdlib.free(tags)
    
            return reval
    

You'd need this code to compile with the `--cplus` flag with _Cython_.

**EDIT** : Corrected code, Cython does no more give errors.

