包装 C++包含 wxString 和 Cython 的类

发布于 2024-11-15 14:46:33 字数 527 浏览 6 评论 0原文

我正在开发一个 Python 扩展,以与使用 wxWidgets 为 GUI 编写的 C++ 应用程序结合起来。我正在使用 Cython,并且基本系统(构建工具,加上具有适当版本详细信息的入门扩展等)可以愉快地工作。

我只对提供后端(非 GUI)功能感兴趣,例如文件解析和处理。但是,所有类(不仅仅是 GUI 类)都使用 wxString 来表示字符串数据,例如下面的最小示例:

#include <wx/string.h>

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

我的问题是包装此类类的最佳方法是什么?有没有一种简单的方法可以在 Python 字符串和 wxString 实例之间进行交互?或者我还需要包装 wxString 类吗?我是否能够以某种方式与 wxPython 端口结合起来以避免重新发明轮子?

I'm working on a Python extension to tie in with a C++ application written using wxWidgets for the GUI. I'm using Cython, and have the basic system (build tools, plus a starter extension with appropriate version details etc) happily working.

I'm only interested in making backend (non-GUI) functionality available, such as file parsing and processing. However, all classes - not just the GUI ones - use wxString for string data, such as in the following minimal example:

#include <wx/string.h>

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

My question is what is the best way to go about wrapping such a class? Is there a simple way to interface between a Python string and a wxString instance? Or will I need to wrap the wxString class as well? Am I able to tie in somehow with the wxPython port to avoid re-inventing the wheel?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

翻身的咸鱼 2024-11-22 14:46:33

我通过使用静态 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 它并根据需要调用函数:

cimport wx.string

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

I got it to work by using the static wxString::FromUTF8() function to convert from Python to wxString, and the wxString.ToUTF8() to go in the other direction. The following is the code I came up with:

# 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')

Simply put this in a .pxd file (personally, I put it in a subdirectory as wx/string.pxd - make sure you also create an wx/__init__.pdx if you choose to do the same). Then cimport it and call the functions as appropriate:

cimport wx.string

wx_string = wx.string.from_python(python_string)
python_string = wx.string.to_python_unicode(wx_string)
贵在坚持 2024-11-22 14:46:33

我尝试的第一种方法是使用 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 的 PyString 对象字符缓冲区的方式手动重新实现所有操作。 Cython 可以帮助编写此类子类。

The first approach I would try is to use the wxString constructor:

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

and pass the const char* string to it to create the object.

Then write some inline functions to convert from python string to wxString and vice versa.

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

Now the only downside I see is that the string might be duplicate in wxString and python world.

A Second Approach would be to subclass wxString and hand reimplement all the operations in a way that uses the Python's PyString Object character buffer. Cython can help in coding such subclass.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文