Обтекание классов C ++, содержащих wxString, с помощью Cython - PullRequest
3 голосов
/ 16 июня 2011

Я работаю над расширением Python для связи с приложением C ++, написанным с использованием wxWidgets для GUI.Я использую Cython, и у меня успешно работает базовая система (инструменты сборки, плюс начальное расширение с соответствующими сведениями о версии и т. Д.).

Я заинтересован только в том, чтобы сделать доступной функциональность бэкэнда (не GUI)такие как разбор и обработка файлов.Тем не менее, все классы - не только GUI - используют wxString для строковых данных, как, например, в следующем минимальном примере:

#include <wx/string.h>

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

Мой вопрос заключается в том, как лучше всего обернуть такуюучебный класс?Есть ли простой способ взаимодействия между строкой Python и экземпляром wxString?Или мне нужно будет также обернуть класс wxString?Могу ли я каким-то образом подключиться к порту wxPython, чтобы не изобретать велосипед заново?

Ответы [ 2 ]

2 голосов
/ 19 июня 2011

Я заставил его работать, используя статическую функцию wxString::FromUTF8() для преобразования из 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 it и вызовите соответствующие функции:

cimport wx.string

wx_string = wx.string.from_python(python_string)
python_string = wx.string.to_python_unicode(wx_string)
0 голосов
/ 16 июня 2011

Первый подход, который я бы попробовал, это использовать конструктор 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.

Второй подход будетсоздать подкласс wxString и вручную переопределить все операции таким образом, чтобы использовать буфер символов Python Object Object в Python.Cython может помочь в кодировании такого подкласса.

...