15.4 在C扩展模块中操作隐形指针

    隐形结构体可以很容易的通过将它们包装在胶囊对象中来处理。考虑我们例子代码中的下列C代码片段:

    下面是一个使用胶囊包装Point结构体和 函数的扩展代码实例:

    胶囊和C指针类似。在内部,它们获取一个通用指针和一个名称,可以使用 PyCapsule_New() 函数很容易的被创建。另外,一个可选的析构函数能被绑定到胶囊上,用来在胶囊对象被垃圾回收时释放底层的内存。

    要提取胶囊中的指针,可使用 PyCapsule_GetPointer() 函数并指定名称。如果提供的名称和胶囊不匹配或其他错误出现,那么就会抛出异常并返回NULL。

    对于胶囊对象一个难点在于垃圾回收和内存管理。PyPoint_FromPoint() 函数接受一个 参数,用来指定当胶囊被销毁时底层Point * 结构体是否应该被回收。在某些C代码中,归属问题通常很难被处理(比如一个Point结构体被嵌入到一个被单独管理的大结构体中)。程序员可以使用 extra 参数来控制,而不是单方面的决定垃圾回收。要注意的是和现有胶囊有关的析构器能使用 PyCapsule_SetDestructor() 函数来更改。

    对于涉及到结构体的C代码而言,使用胶囊是一个比较合理的解决方案。例如,有时候你并不关心暴露结构体的内部信息或者将其转换成一个完整的扩展类型。通过使用胶囊,你可以在它上面放一个轻量级的包装器,然后将它传给其他的扩展函数。