You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Python C API判断decimal.Decimal类型并调用函数完成转换

问题1:检测对象是否为decimal.Decimal类型

不需要依赖decimal模块未导出的内部宏/类型定义,最优的兼容方案是通过Python公共API导入Decimal类型后做类型校验,具体实现逻辑:

  1. 在你的扩展模块初始化阶段,导入decimal模块并获取Decimal类的引用,存储为全局静态变量:
static PyObject *global_decimal_type = NULL;

// 模块初始化函数中添加如下逻辑
PyObject *decimal_module = PyImport_ImportModule("decimal");
if (decimal_module == NULL) {
    // 处理导入失败的情况,比如模块不存在时抛导入错误
    return NULL;
}
global_decimal_type = PyObject_GetAttrString(decimal_module, "Decimal");
Py_DECREF(decimal_module);
if (global_decimal_type == NULL) {
    return NULL;
}
// 注意要持有类型对象的引用,避免被GC回收
Py_INCREF(global_decimal_type);
  1. 类型检测时直接调用PyObject_IsInstance即可:
int is_decimal = PyObject_IsInstance(value, global_decimal_type);
if (is_decimal < 0) {
    // 处理检测过程中抛出的异常
    return NULL;
}
if (is_decimal) {
    // 是Decimal类型的逻辑
}

这个方案完全依赖Python公共API,兼容所有支持decimal模块的Python版本,不会因为CPython内部实现变更失效。

问题2:可调用对象的调用

你找到的PyObject_CallObject是正确的API,str、float本身就是Python层面的可调用对象,之前调用失败大概率是参数处理或者异常校验遗漏导致的,完整的调用逻辑需要补充如下注意点:

  1. 调用前先校验传入的func是否可调用,避免后续调用出错:
if (!PyCallable_Check(func)) {
    PyErr_SetString(PyExc_TypeError, "第二个参数必须是可调用对象");
    return NULL;
}
  1. 调用时注意内存管理,PyTuple_Pack返回的是新引用,调用完成后需要手动释放,避免内存泄漏:
PyObject *args = PyTuple_Pack(1, value);
if (args == NULL) {
    return NULL;
}
PyObject *result = PyObject_CallObject(func, args);
Py_DECREF(args); // 释放参数元组
if (result == NULL) {
    // 处理调用过程中抛出的异常
    return NULL;
}
// 后续处理result逻辑

不需要改为传字符串参数,直接传入str、float或者用户自定义的单参数可调用对象都可以通过上述逻辑正常执行。

内容的提问来源于stack exchange,提问作者Bryant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 20:09:03