首先,我将回答您实际提出的问题。
在 C 中创建一个struct State
,就像不涉及 Python 一样。
如果你不打算复制这些(你只通过它们struct State *
),那么你可以只(intptr_t)theStatePtr
为 Python 获取一个 id。当然,您确实需要注意 Python 对象的生命周期永远不会超过 C 对象的生命周期,但这是可行的。
如果您出于某种原因确实需要复制/移动结构,或者您需要更多帮助来管理状态(例如,将 Python id 视为弱引用),请选择适当的集合(哈希表、树、数组等)您的用例,然后将密钥作为 id 传递给 Python。
但是,我认为您可能在这里优化了错误的部分。来回传递对象没什么——它只是一个指针副本。重新计数可能是一个问题,但很少发生,而且您从生命周期管理中获得的好处通常是值得的。可能会影响性能的部分是您的 C 代码不断将一堆 Python 整数转换为 Cint
等。如果这是您的问题,只需创建一个具有 C 状态的 C 结构,并将其包装在一个不支持的 Python 对象中将任何内部结构暴露到 Python 中。
最后,您真的需要在这里进行任何优化吗?如果您正在做 CPU 密集型工作,我敢打赌,真正的工作完全掩盖了 Python 对象访问的成本,后者甚至不会出现在分析中。如果您还没有进行分析,那绝对是您应该做的第一件事,因为这里的正确答案很可能是“不要费心做任何事情”。
更进一步:如果您只是在 C 中编写 C 代码以进行优化,您确定还需要它吗?在 C 中处理内存管理是烦人且容易出错的,在 Python 的 C 扩展模块中处理它更是如此,当你不知道它是如何工作的时第一次这样做几乎是保证支出的秘诀你所有的时间都在追踪段错误和泄漏,而不是编写你的实际代码。因此,我将按顺序尝试以下操作,对每个进行分析,并且仅在太慢时才将列表向下移动:
- 只需用 Python 编写算法,并使用现有的 CPython 解释器。
- 确保你有一个最佳算法。
- 尝试 PyPy 而不是 CPython。
- 获取Cython并尝试使用尽可能少的更改来编译您的 Python 代码。
- 根据需要修改您的代码以利用 Cython 功能,例如静态类型、直接调用 C 函数等。
- 用 C 语言编写低级代码,用 Cython 或使用
ctypes
.
- 使用您最喜欢的接口机制,用 C 语言编写整个低级和中级。这可能仍然不是本机 C API,除非您有很多经验并且正在做一些非常简单的事情。