2011-06-16 51 views
3

我正在研究Python擴展,以便與使用wxWidgets爲GUI編寫的C++應用程序配合使用。我正在使用Cython,並且擁有基本的系統(構建工具,以及具有適當版本詳細信息的入門級擴展等),愉快地工作。使用Cython封裝包含wxString的C++類

我只想讓後端(非GUI)功能可用,如文件解析和處理。然而,所有的類 - 不僅僅是那些GUI - 使用wxString對於字符串數據,如下面的小例子:

#include <wx/string.h> 

class MyClass{ 
    wxString name; 
    wxString get_name(){ 
     return this->name; 
    } 
}; 

我的問題是什麼是去包裹這樣一類的最佳方式?有沒有一種簡單的方法來連接Python字符串和wxString實例?或者我還需要包裝wxString課程?我能夠以某種方式與wxPython端口配合以避免重新發明輪子?

回答

2

我通過使用靜態wxString::FromUTF8()函數將Python從Python轉換爲wxString,並將wxString.ToUTF8()轉換爲其他方向,從而實現了它的功能。以下是我想出了代碼:

# Import the parts of wxString we want to use. 
cdef extern from "wx/string.h": 
    cdef cppclass wxString: 
     char* ToUTF8() 


# Import useful static functions from the class. 
cdef extern from "wx/string.h" namespace "wxString": 
    wxString FromUTF8(char*) 


# Function to convert from Python string to wxString. This can be given either 
# a unicode string, or a UTF-8 encoded byte string. Results with other encodings 
# are undefined and will probably lead to errors. 
cdef inline wxString from_python(python_string): 
    # If it is a Python unicode string, encode it to a UTF-8 byte string as this 
    # is how we will pass it to wxString. 
    if isinstance(python_string, unicode): 
     byte_string = python_string.encode('UTF-8') 

    # It is already a byte string, and we have no choice but to assume its valid 
    # UTF-8 as theres no (sane/efficient) way to detect the encoding. 
    else: 
     byte_string = python_string 

    # Turn the byte string (which is still a Python object) into a C-level char* 
    # string. 
    cdef char* c_string = byte_string 

    # Use the static wxString::FromUTF8() function to get us a wxString. 
    return FromUTF8(c_string) 


# Function to convert a wxString to a UTF-8 encoded Python byte string. 
cdef inline object to_python_utf8(wxString wx_string): 
    return wx_string.ToUTF8() 


# Function to convert a wxString to a Python unicode string. 
cdef inline object to_python_unicode(wxString wx_string): 
    # Since the wxString.ToUTF8() method returns a const char*, we'd have to try 
    # and cast it if we wanted to do it all in here. I've tried this and can't 
    # seem to get it to work. But calling the to_python_utf8() function 
    # means Cython handles the conversions and it all just works. Plus, since 
    # they are defined as inline functions this may well be simplified down when 
    # compiled. 
    byte_string = to_python_utf8(wx_string) 

    # Decode it to a unicode string and we're done. 
    return byte_string.decode('UTF-8') 

簡單地說這在.pxd文件(就個人而言,我把它放在一個子目錄wx/string.pxd - 確保你還可以創建一個wx/__init__.pdx,如果你選擇做相同)。然後cimport它並調用適當的功能:

cimport wx.string 

wx_string = wx.string.from_python(python_string) 
python_string = wx.string.to_python_unicode(wx_string) 
0

第一種方法我會嘗試是使用wxString構造:

wxString(const wxChar* psz, size_t nLength = wxSTRING_MAXLEN) 

,並通過爲const char *串它來創建對象。

然後編寫一些內聯函數將python字符串轉換爲wxString,反之亦然。

PyObject* PyString_FromStringAndSize(const char *v, Py_ssize_t len) 

現在唯一的缺點是我看到的字符串可能在wxString和python世界中重複。

第二種方法是以使用Python的PyString對象字符緩衝區的方式將wxString和hand重新實現所有操作。 Cython可以幫助編寫這樣的子類。

+0

感謝您的答案。它讓我走上正確的軌道,讓這個工作。我已經發布我的代碼作爲一個單獨的答案。 – Blair 2011-06-19 04:06:30