如何使用C API在Python C扩展中构造decimal.Decimal对象?
Python C扩展中创建
decimal.Decimal的相关说明 官方文档现状
- 当前Python没有为
decimal.Decimal提供独立的公开稳定C API。 - 官方C API文档的「其他内置对象」分类仅覆盖解释器核心内置类型的接口,
decimal作为标准库实现,其C层接口属于实现细节,未纳入公开文档体系。 - 你在源码中定位到的
_decimal模块接口,是C加速实现的内部定义,没有向后兼容性承诺,不属于可对外依赖的公开API范畴。
可行实现方案
方案1:通过C API调用Python层构造逻辑(兼容性最优,推荐使用)
不需要依赖未公开的内部头文件,直接通过标准C API调用decimal模块的公开类构造实例,完全没有版本兼容风险。参考流程:
- 导入
decimal模块// 导入模块 PyObject* decimal_mod = PyImport_ImportModule("decimal"); if (decimal_mod == NULL) { // 补充导入失败的错误处理 } - 获取模块下的
Decimal类型对象PyObject* Decimal_cls = PyObject_GetAttrString(decimal_mod, "Decimal"); Py_DECREF(decimal_mod); // 用完即可释放模块引用 if (Decimal_cls == NULL) { // 补充获取类型失败的错误处理 } - 调用类构造函数生成实例,优先传入字符串参数避免精度损失
// 示例:从字符串构造Decimal实例 const char* init_value = "987.654"; PyObject* args = Py_BuildValue("(s)", init_value); PyObject* decimal_instance = PyObject_CallObject(Decimal_cls, args); // 释放临时参数对象 Py_DECREF(args); Py_DECREF(Decimal_cls); if (decimal_instance == NULL) { // 补充构造失败的错误处理 }
- 该方式走的是完全公开的Python层接口,跨Python版本适配成本极低,不需要针对不同CPython版本调整内部结构访问逻辑。
方案2:直接调用_decimal模块内部接口(仅适合固定版本的高性能场景)
如果需要消除Python层调用的开销,可直接导入内置_decimal模块获取其暴露的C实现对象:
- 导入
_decimal模块后获取的Decimal属性,与Python层的decimal.Decimal是同一个类型对象。 - 所有需要的构造、操作逻辑都可以通过模块暴露的C方法实现,不需要硬编码内部结构偏移,仅需注意这类接口没有官方兼容性承诺,升级Python版本时需要同步验证适配性。
参考资源
- 没有官方提供的面向第三方扩展开发者的Decimal C API示例,可参考的官方实现仅为CPython源码中
_decimal模块本身的实现逻辑,其中包含完整的类型定义、构造流程、字段访问规则。 - 标准库内置的C扩展中,没有其他模块直接操作Decimal内部结构的案例,绝大多数场景下都采用方案1的调用逻辑处理Decimal对象。
内容的提问来源于stack exchange,提问作者Bryant
相关产品推荐
相关产品推荐

