2012-02-29 10 views
1

現在、Pythonで高速POSタグ付け実装が必要なNLPアプリケーションを作成しています。タグラーはC++ラッパーインターフェースを持っています。PythonでC++ライブラリをラップしてカスタムタイプを処理する

#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; 
} 

私は決してPythonでC++のラッパーを書いたことがありません。だから、いくつかの質問があります:

  1. 私はカスタムC++クラスのインスタンスをPythonで保存できますか? これまで私はそれを見たことがありません。私が行ったすべての例は、基本的なデータ型のみを返しました。 (このposタグャーは言語セットで初期化する必要がありますが、メモリにロードするには時間がかかるため、すべてのタグ付けプロシージャーを作成するためにラッパーを書き直すのではなく、初期化して保管するだけですタグ付き文字列)

  2. 1が可能な場合:最も簡単な方法は何ですか?

+0

Cにはクラスがありません。 C++を意味しますか? – Daenyth

+0

@Daenyth申し訳ありませんが、投稿を編集しました。 –

答えて

3

私はこの目的でCythonを使用することを提案します。 C/C++エクステンション型の記述は単純です。

残念ながら、あなたが使用するヘッダーなしではテストできないため、このコードを完全に修正することはできません。 #コーディング:UTF-8 #ファイル: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 

あなたはCython--cplusフラグを使用してコンパイルするために、このコードが必要と思います。

EDIT:修正されたコード、Cythonはエラーを返しません。

+0

まずは時間を割いていただき、ありがとうございます。ほんとうにありがとう! cythonは私に複数のコンパイルエラーを与えますが、それは主にcythonがcharへのダブルポインタをコンパイルできないためです。ソースコードはhttp://www.ims.uni-stuttgart.de/projekte/corplex/RFTagger/から得ることができます。 –

+0

は、44行目と52行目の '_words'の2つのタイプミスを編集しました。 28行目でエラーが発生します。boolは型識別子ではありません。 –

+0

@sebastianmarkow私はコードを編集しましたが、Cythonは私に今何かエラーを与えません。すでに述べたようにいくつかの名前を混乱させ、 'bool'を' bint'に変更するのを忘れました。そして、私は2つの場所の最後にc-datatype変数の下線を付けました。とにかく、依存関係はライブラリが必要ですか? g ++でコンパイルすると多くのエラーが発生します。 –

0

最も簡単なことは、Pythonでプッシュできるが、クライアントは気にする必要がない不透明な型を作成することです。

+0

どうすればいいですか?どんな例?あなたが私を指すことができるどこにドキュメント? –

+0

通常のextemb docには、型を作成するための例があります。ポインタを保持する属性を追加するだけです。 –

関連する問題