CPython - 在作为参数传递的 C 函数中读取 Python 字典 (keys/values)
CPython - Read Python Dictionary (keys/values) inside a C Function Passed as argument
我正在编写 Python C 扩展。我正在将 Python dict
传递给 C 函数。我可以使用以下代码解析它:
PyObject *large_dict = NULL;
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &large_dict)) return NULL;
if (large_dict != NULL)
{
printf("Large Dictionary Not Null\n");
}
这里打印了“Large Dictionary Not Null”语句,表示字典解析成功。
现在我想通过指定键来访问字典值,就像我们在 Python 中所做的那样。例如,large_dict['k1']
将给出值 v1
。
如何在这个 C 函数中访问字典 keys/values?
您应该完成 link、https://docs.python.org/2/c-api/dict.html
摘录如下,
PyObject* PyDict_GetItem(PyObject *p, PyObject *key)
Return value: Borrowed reference.
Return the object from dictionary p which has a key key. Return NULL if the key key is not present, but without setting an exception.
PyObject* PyDict_GetItemString(PyObject *p, const char *key)
Return value: Borrowed reference.
This is the same as PyDict_GetItem(), but key is specified as a char*, rather than a PyObject*.
PyObject* PyDict_Items(PyObject *p)
Return value: New reference.
Return a PyListObject containing all the items from the dictionary, as in the dictionary method dict.items().
PyObject* PyDict_Keys(PyObject *p)
Return value: New reference.
Return a PyListObject containing all the keys from the dictionary, as in the dictionary method dict.keys().
PyObject* PyDict_Values(PyObject *p)
Return value: New reference.
Return a PyListObject containing all the values from the dictionary p, as in the dictionary method dict.values().
关注borrowed reference / new reference
。在为 Python 扩展编码时有点棘手。
我会回复 Python 3.7+,因为这是目前最有可能的用例(参见 reference)。转换 from/to C 类型取决于您未指定的 keys/values 的 Python 类型。为了说明实际用例,我们假设键和值都是正整数。然后,如果您想检索 k1=42
的值,那么我认为您可以这样做:
unsigned int k1 = 42;
PyObject *py_k1 = PyLong_FromUnsignedLong(k1);
PyObject *py_v1 = PyDict_GetItem(large_dict, py_k1);
unsigned int v1 = PyLong_AsUnsignedLong(py_v1);
逐行分解,第一行将密钥定义为纯 C unsigned int
。但是我们不能使用常规 C 类型来索引 Python 字典,因此在第二行中我们定义了一个指向 Python 类型的指针,该类型将指向键。然后我们通过 PyDict_GetItem
执行 Python 的 large_dict[k1]
的 C 等价物,但使用我们创建的指针作为键并获得指向 Python 类型的指针作为值.最后,如果我们想访问作为常规 C 类型的值,我们需要在最后一行对其进行转换,这与我们在第二行所做的相反。
注意:PyDict_GetItem
returns 借用引用,所以我们不需要担心引用计数。
我正在编写 Python C 扩展。我正在将 Python dict
传递给 C 函数。我可以使用以下代码解析它:
PyObject *large_dict = NULL;
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &large_dict)) return NULL;
if (large_dict != NULL)
{
printf("Large Dictionary Not Null\n");
}
这里打印了“Large Dictionary Not Null”语句,表示字典解析成功。
现在我想通过指定键来访问字典值,就像我们在 Python 中所做的那样。例如,large_dict['k1']
将给出值 v1
。
如何在这个 C 函数中访问字典 keys/values?
您应该完成 link、https://docs.python.org/2/c-api/dict.html 摘录如下,
PyObject* PyDict_GetItem(PyObject *p, PyObject *key)
Return value: Borrowed reference.
Return the object from dictionary p which has a key key. Return NULL if the key key is not present, but without setting an exception.
PyObject* PyDict_GetItemString(PyObject *p, const char *key)
Return value: Borrowed reference.
This is the same as PyDict_GetItem(), but key is specified as a char*, rather than a PyObject*.
PyObject* PyDict_Items(PyObject *p)
Return value: New reference.
Return a PyListObject containing all the items from the dictionary, as in the dictionary method dict.items().
PyObject* PyDict_Keys(PyObject *p)
Return value: New reference.
Return a PyListObject containing all the keys from the dictionary, as in the dictionary method dict.keys().
PyObject* PyDict_Values(PyObject *p)
Return value: New reference.
Return a PyListObject containing all the values from the dictionary p, as in the dictionary method dict.values().
关注borrowed reference / new reference
。在为 Python 扩展编码时有点棘手。
我会回复 Python 3.7+,因为这是目前最有可能的用例(参见 reference)。转换 from/to C 类型取决于您未指定的 keys/values 的 Python 类型。为了说明实际用例,我们假设键和值都是正整数。然后,如果您想检索 k1=42
的值,那么我认为您可以这样做:
unsigned int k1 = 42;
PyObject *py_k1 = PyLong_FromUnsignedLong(k1);
PyObject *py_v1 = PyDict_GetItem(large_dict, py_k1);
unsigned int v1 = PyLong_AsUnsignedLong(py_v1);
逐行分解,第一行将密钥定义为纯 C unsigned int
。但是我们不能使用常规 C 类型来索引 Python 字典,因此在第二行中我们定义了一个指向 Python 类型的指针,该类型将指向键。然后我们通过 PyDict_GetItem
执行 Python 的 large_dict[k1]
的 C 等价物,但使用我们创建的指针作为键并获得指向 Python 类型的指针作为值.最后,如果我们想访问作为常规 C 类型的值,我们需要在最后一行对其进行转换,这与我们在第二行所做的相反。
注意:PyDict_GetItem
returns 借用引用,所以我们不需要担心引用计数。