Python C-API 访问字符串常量
Python C-API access String constants
我想使用 python 的 C-API 在 C 中实现我为 python 编写的库。在 python 中,我可以通过声明 "constants" 在我的模块中声明:
RED = "red" # Not really a constant, I know
BLUE = "blue" # but suitable, nevertheless
def solve(img_h):
# Awesome computations
return (RED, BLUE)[some_flag]
这些常量随后由模块提供的函数return编辑。我在 C 中做同样的事情时遇到了一些麻烦。这是我到目前为止得到的结果:
PyMODINIT_FUNC
PyInit_puzzler(void)
{
PyObject* module = PyModule_Create(&Module);
(void) PyModule_AddStringConstant(module, "BLUE", "blue");
(void) PyModule_AddStringConstant(module, "RED", "red");
return module;
}
PyObject* solve(PyObject* module, PyObject* file_handle)
{
// Do some awesome computations based on the file
// Involves HUGE amounts of memory management, thus efficient in C
// PROBLEM: How do I return the StringConstants from here?
return some_flag ? BLUE : RED;
}
我已经把有问题的部分标出来了。在我使用 PyModule_AddStringConstant(module, "FOO", "foo");
将字符串常量添加到模块后,我如何才能从我的方法中将它们实际 return 作为 PyObject*
?当我 return 它们时,我需要增加 ref-counter 吗?
因为 PyModule_AddStringConstant(module, name, value) adds the constant to the module, it should be available from the module's dictionary which can be acquired with PyModule_GetDict(module). You can then access any attribute from the module via its dictionary using PyDict_GetItemString(dict, key) 这是您可以从模块访问常量的方式(在定义之后):
// Get module dict. This is a borrowed reference.
PyObject* module_dict = PyModule_GetDict(module);
// Get BLUE constant. This is a borrowed reference.
PyObject* BLUE = PyDict_GetItemString(module_dict, "BLUE");
// Get RED constant. This is a borrowed reference.
PyObject* RED = PyDict_GetItemString(module_dict, "RED");
要将此与您的 solve()
函数放在一起,您需要类似于:
PyObject* solve(PyObject* module, PyObject* file_handle)
{
// Do some awesome computations based on the file
// Involves HUGE amounts of memory management, thus efficient in C
// Return string constant at the end.
PyObject* module_dict = PyModule_GetDict(module);
PyObject* constant = NULL;
if (some_flag) {
// Return BLUE constant. Since BLUE is a borrowed
// reference, increment its reference count before
// returning it.
constant = PyDict_GetItemString(module_dict, "BLUE");
Py_INCREF(constant);
} else {
// Return RED constant. Since RED is a borrowed
// reference, increment its reference count before
// returning it.
constant = PyDict_GetItemString(module_dict, "RED");
Py_INCREF(constant);
}
// NOTE: Before you return, make sure to release any owned
// references that this function acquired. `module_dict` does
// not need to be released because it is merely "borrowed".
// Return the constant (either BLUE or RED) as an owned
// reference. Whatever calls `solve()` must make sure to
// release the returned reference with `Py_DECREF()`.
return constant;
}
我想使用 python 的 C-API 在 C 中实现我为 python 编写的库。在 python 中,我可以通过声明 "constants" 在我的模块中声明:
RED = "red" # Not really a constant, I know
BLUE = "blue" # but suitable, nevertheless
def solve(img_h):
# Awesome computations
return (RED, BLUE)[some_flag]
这些常量随后由模块提供的函数return编辑。我在 C 中做同样的事情时遇到了一些麻烦。这是我到目前为止得到的结果:
PyMODINIT_FUNC
PyInit_puzzler(void)
{
PyObject* module = PyModule_Create(&Module);
(void) PyModule_AddStringConstant(module, "BLUE", "blue");
(void) PyModule_AddStringConstant(module, "RED", "red");
return module;
}
PyObject* solve(PyObject* module, PyObject* file_handle)
{
// Do some awesome computations based on the file
// Involves HUGE amounts of memory management, thus efficient in C
// PROBLEM: How do I return the StringConstants from here?
return some_flag ? BLUE : RED;
}
我已经把有问题的部分标出来了。在我使用 PyModule_AddStringConstant(module, "FOO", "foo");
将字符串常量添加到模块后,我如何才能从我的方法中将它们实际 return 作为 PyObject*
?当我 return 它们时,我需要增加 ref-counter 吗?
因为 PyModule_AddStringConstant(module, name, value) adds the constant to the module, it should be available from the module's dictionary which can be acquired with PyModule_GetDict(module). You can then access any attribute from the module via its dictionary using PyDict_GetItemString(dict, key) 这是您可以从模块访问常量的方式(在定义之后):
// Get module dict. This is a borrowed reference.
PyObject* module_dict = PyModule_GetDict(module);
// Get BLUE constant. This is a borrowed reference.
PyObject* BLUE = PyDict_GetItemString(module_dict, "BLUE");
// Get RED constant. This is a borrowed reference.
PyObject* RED = PyDict_GetItemString(module_dict, "RED");
要将此与您的 solve()
函数放在一起,您需要类似于:
PyObject* solve(PyObject* module, PyObject* file_handle)
{
// Do some awesome computations based on the file
// Involves HUGE amounts of memory management, thus efficient in C
// Return string constant at the end.
PyObject* module_dict = PyModule_GetDict(module);
PyObject* constant = NULL;
if (some_flag) {
// Return BLUE constant. Since BLUE is a borrowed
// reference, increment its reference count before
// returning it.
constant = PyDict_GetItemString(module_dict, "BLUE");
Py_INCREF(constant);
} else {
// Return RED constant. Since RED is a borrowed
// reference, increment its reference count before
// returning it.
constant = PyDict_GetItemString(module_dict, "RED");
Py_INCREF(constant);
}
// NOTE: Before you return, make sure to release any owned
// references that this function acquired. `module_dict` does
// not need to be released because it is merely "borrowed".
// Return the constant (either BLUE or RED) as an owned
// reference. Whatever calls `solve()` must make sure to
// release the returned reference with `Py_DECREF()`.
return constant;
}