【问题标题】:How to manage string memory with python ctypes如何使用 python ctypes 管理字符串内存
【发布时间】:2011-06-03 16:00:25
【问题描述】:

我的 Python 代码正在调用本机库(也是我编写的)中的 C 函数。该函数将两个字符串作为参数并将其响应作为字符串返回。 python 传递给 C 库的两个参数字符串只有 C 库读取,所以我不担心它们的内存管理。 AFAIK,它们的内存将由 python 分配,并在 python 运行时看起来合适时释放。

但是,我知道 C 库返回的字符串的内存必须明确管理。我可以实现它的一种方法是:C 函数 callocs 一个字符数组,用答案填充它并从函数返回。 python 代码使用返回的字符串,并且应该在该字符串上调用 libc 的 free 或调用同一 C 库的另一个函数,该函数将负责释放内存。

还有其他方法可以做到这一点吗? ctype 是否提供任何实用函数来简化本地库返回的数据结构的内存释放?

【问题讨论】:

    标签: python memory-management ctypes


    【解决方案1】:

    我强烈建议不要在通过 ctypes 调用的外部函数中分配内存并从 Python 中释放此内存。尽可能在 Python 中分配内存。

    在您的情况下,如果您事先知道返回字符串长度的上限,请使用

    buf = ctypes.create_string_buffer(upper_limt)
    

    在 Python 中分配内存并将指向该内存的指针传递给您的函数。

    【讨论】:

    • 理论上这可能会导致缓冲区溢出。
    • @Noctis:这就是为什么我说“如果你事先知道返回字符串长度的上限”。
    • @chmike 我认为是,如果你可以保证一个上限。您的 C API 应确保它不超过此限制,如下面 Jim 的回答所述。
    • @SvenMarnach 如果我理解正确,一个更简单的解决方案和正确答案是将函数的返回类型声明为c_char_p。然后 ctypes 会将返回的字符串复制到 python 字符串中并释放返回的字符串。
    • @chmike 虽然 ctypes 在将字符串数据转换为字节对象时会复制字符串数据,但它绝对不会释放字符指针指向的数据。完全不清楚指针是否指向使用malloc() 在堆上分配的字符串——在绝大多数情况下它不会,因此尝试默认释放它会使ctypes 或多或少不可用。如果返回的字符串实际上是堆分配的,那么按照你建议的路线走会泄漏数据。
    【解决方案2】:

    执行此操作的常用方法是向 C 函数添加额外的缓冲区参数和长度参数。如果调用函数时缓冲区大小小于所需大小,则该函数仅返回所需缓冲区大小而不执行其他操作,否则将数据复制到缓冲区中并将大小设置为实际大小复制的数据。

    这允许您在 Python 中管理缓冲区,但代价是向您的 C 函数添加 2 个额外参数。

    【讨论】:

      猜你喜欢
      • 2020-02-16
      • 2021-11-23
      • 2014-06-16
      • 2010-10-11
      • 2011-10-22
      • 1970-01-01
      • 1970-01-01
      • 2021-07-28
      • 2013-06-17
      相关资源
      最近更新 更多