使用 C API 确定 python 中小数对象的类型并转换为不同类型

Determining type of decimal object in python with C API and converting to different type

我正在通过 Python C API 在 C 中编写一个 python 模块。这个简短的 python 片段可能最能说明我想做的事情:

def convert(value, func):
    if isinstance(value, decimal.Decimal):
        return func(value)
    return value

其中 func 很可能是 strfloat,但也可以是采用单个参数的用户定义函数。我一直在努力回答有关这种方法的几个问题。

  1. 如何检查类型 decimal.Decimal。我可以在 decimal code that they've defined some un-exported macros and typedefs that would assist this this, but as they are un-exported I cannot use them (as far as I know). I searched SO and found some posts that look promising 中看到,但由于它是 9 年前的 question/answer,我不确定它是否是最好的方法。

  2. 我尝试过将 strfloat 传递到我在 C 中定义的函数中,但我无法让它们正确执行。我不确定如何使用 PyObject 作为函数指针并调用它。我发现最接近的是 PyObject_Callfloatstr 似乎不是可调用的。我是否需要做其他事情,比如接受一个可以是字符串的参数('float',或 'str'),然后在十进制对象上调用 PyObject_Str 或 PyFloat_FromString(一次我已将其标识为小数),或者是否有某种方法可以将通用函数指针传递给 C API,该指针采用单个位置参数并使用我选择的 argument/value 调用它?

更新:我已经学会了如何做 #2。你可以使用

PyObject_CallObject(func, PyTuple_Pack(1, value))

调用传递给 C 函数的函数指针。

我终于发现了如何完成这两个部分。

对于 1.

PyObject_CallObject(func, PyTuple_Pack(1, value))

(请注意,PyTuple_Pack return 是一个新引用,因此在使用后需要对其进行递减,为清楚起见,我将其省略)。

2.

int _check_decimal(PyObject *value)
{
    PyObject *module = PyImport_ImportModule((char *) "decimal");
    PyObject* moduleDict = PyModule_GetDict(module);
    PyObject* class = PyDict_GetItemString(moduleDict, "Decimal");

    return PyObject_IsInstance(value, class);
}

(再次注意,其中一些 return 引用需要管理)