【问题标题】:create_string_buffer throwing error TypeError: str/bytes expected instead of str instancecreate_string_buffer 抛出错误 TypeError: str/bytes expected 而不是 str instance
【发布时间】:2011-11-06 10:03:06
【问题描述】:

我正在尝试这个简单的 ctypes 示例并收到提到的错误

>>> from ctypes import create_string_buffer
>>> str = create_string_buffer("hello")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python32\lib\ctypes\__init__.py", line 59, in create_string_buffer
buf.value = init
TypeError: str/bytes expected instead of str instance

有谁知道我做错了什么?

同样,我试图将指向字符串的指针从我的 python 代码传递给 C 函数,以便我可以在那里执行一些字符串操作并返回另一个字符串。有人可以给我一些示例代码吗?

extern "C" __declspec(dllexport) char * echo(char* c)
{
      // do stuff
    return c;
}

【问题讨论】:

  • 请永远不要分配给str(这不是这里的问题)。隐藏内置函数是邪恶的。

标签: python string pointers ctypes


【解决方案1】:

您使用的是 Python 3,而 Python 3 中的字符串 (str-type) 是 Unicode 对象。 create_string_buffer 创建 C char 数组,因此您需要传递 bytes 对象。如果您有一个 str 对象,使用适当的编码来创建一个 bytes 对象。请注意,有一个 create_unicode_buffer 也可以创建 C wchar 数组并采用 Python 3 str 对象。

Python 3.2.1 (default, Jul 10 2011, 21:51:15) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.create_unicode_buffer('abcd')
<ctypes.c_wchar_Array_5 object at 0x00C2D300>
>>> ctypes.create_string_buffer(b'abcd')
<ctypes.c_char_Array_5 object at 0x00C2D1C0>
>>> ctypes.create_string_buffer('abcd'.encode('utf-8'))
<ctypes.c_char_Array_5 object at 0x00C2D300>

关于您问题的第二部分,您是要编辑现有字符串还是返回分配在堆上的全新字符串?如果是前者,使用create_string_buffer 将可变字符串传递给函数,然后就地修改它就可以了。下面是一个从 Windows MSVCRT 库调用 _strupr() 的简单示例:

Python 3.2.1 (default, Jul 10 2011, 21:51:15) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> c = ctypes.CDLL('msvcr90.dll')
>>> strupr = c._strupr
>>> a=ctypes.create_string_buffer(b'abc')
>>> strupr.restype=ctypes.c_char_p
>>> strupr(a)
b'ABC'

注意将函数的restype(结果类型)设置为c_char_p告诉ctypes将返回值转换为bytes对象。另请注意,_strupr 会就地转换字符串,因此必须传递可变字符串缓冲区。仅将 Python 字节字符串传递给采用 const char* 的 C 函数,因为直接通过 ctypes 修改 Python 字符串是BadTM

【讨论】:

  • ctypes.create_unicode_buffer('abcd') 适合您吗?它不适用于我在 Ubuntu 11.04 64 位上的 Python 3.2(不是我看到的 3.2.1),而且显然不适用于 @Helali。
  • 是的,它对我有用。我查看了 3.2.1 的发行说明,并没有看到需要 bytescreate_string_buffer 作为修复,但我确实发现了这个问题 (bugs.python.org/issue8306) 说 strbytes 隐式转换不应该被允许。
【解决方案2】:

关于让它工作,如果你传递一个bytes 对象,它就可以工作:

>>> import ctypes
>>> ctypes.create_string_buffer(b'hello')
<ctypes.c_char_Array_6 object at 0x25258c0>

查看create_string_buffer的代码:

def create_string_buffer(init, size=None):
    """create_string_buffer(aBytes) -> character array
    create_string_buffer(anInteger) -> character array
    create_string_buffer(aString, anInteger) -> character array
    """
    if isinstance(init, (str, bytes)):
        if size is None:
            size = len(init)+1
        buftype = c_char * size
        buf = buftype()
        buf.value = init
        return buf
    elif isinstance(init, int):
        buftype = c_char * init
        buf = buftype()
        return buf
    raise TypeError(init)

直接做,

>>> (ctypes.c_char * 10)().value = b'123456789'

这很好用。

>>> (ctypes.c_char * 10)().value = '123456789'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: str/bytes expected instead of str instance

这显示了相同的行为。在我看来,你好像发现了一个错误。

是时候访问http://bugs.python.org了。有一些与c_charcreate_string_buffer 相关的错误在同一个字段中,但没有人报告给它一个str 现在失败(但有明确的例子表明它曾经在Py3K 中工作)。

【讨论】:

  • 感谢作为字节对象传递的解决方案。你能回答问题的后半部分吗?如何打印从 python 中的 C 方法返回的字符串值作为指针?
  • @Helali:我不知道。我从未在 Python 中处理过 C 代码。如果你有一个 ctypes.c_char_Array_* 实例,它只是 thingy.value,但我想这不是你的问题。
  • @eryksun:我不在乎; c_char 数组用于 接受str,并且仍然声称但不再。因此,它是一种回归。他们是否选择改变记录的行为而不是修复回归是他们的选择。但这是一个错误。
【解决方案3】:

参数是字符串所需的缓冲区大小,因此将缓冲区的长度传递给它。它将创建一个该大小的 char 数组。

>>> from ctypes import create_string_buffer
>>> buf = create_string_buffer(20)
>>> buf
<ctypes.c_char_Array_20 object at 0x355348>
>>> 

【讨论】:

  • 嗯,我明白了。但是如何将该缓冲区初始化为字符串值?最后,我怎样才能将它传递给 C 方法?谢谢。
猜你喜欢
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-07
  • 1970-01-01
  • 2021-11-07
  • 2021-02-07
相关资源
最近更新 更多