如何将 C 变量作为变量公开给 Python?
How do I expose a C variable to Python as a variable?
假设在用 C 编写的自定义 python 模块中,我声明变量:
static int module_state;
我的模块中的函数设置了这个变量的状态。如果我想知道 module_state
的值,我可以像这样声明一个 getter 函数:
PyObject * get_module_state(PyObject *self)
{
return PyLong_FromLong(module_state);
}
在 python (3) 我可以简单地做:
import module
...
state = module.get_module_state()
但是,我想将它公开为一个变量:
import module
state = module.module_state
我查看了 API 中的 PyMemberDef
和 PyGetterSetterDef
,但我对如何使用它们公开变量感到困惑。一般来说,我不希望 python 用户能够修改变量。
这个变量的用途与errno
非常相似,我想让它尽可能透明地可用。
Can modules have properties the same way that objects can? 中的两个主要建议实际上可以非常“轻松”地翻译成 C。
模块级 __getattr__
。这需要Python 3.7。您只需使用 the normal C API mechanism, PyMethodDef
.
定义一个名为 __getattr__
的函数
这个函数会做这样的事情:
if (PyUnicode_CompareWithASCIIString(arg, "name") == 0) {
return PyLong_FromLong(your_variable);
}
else {
PyErr_SetObject(PyExc_AttributeError, arg);
return NULL;
}
请注意,限制(我认为您可以接受)是该变量将是只读的,因为没有等效的模块 __setattr__
。
使用 class 代替模块。这可以是在 C 中定义的 class,PyMemberDef
将 C 变量公开为 属性.
这可能最适合子模块(例如 main_mod.submod
)。这样主模块可以将您的 class 实例添加到 sys.modules
中,例如:
PyObject *sys_modules = PySys_GetObject("modules");
PyDict_SetItemString(sys_modules, "main_mod.submod", instance);
我认为这种方法可能比第一种方法麻烦得多,但它可以在 C 中使用。
假设在用 C 编写的自定义 python 模块中,我声明变量:
static int module_state;
我的模块中的函数设置了这个变量的状态。如果我想知道 module_state
的值,我可以像这样声明一个 getter 函数:
PyObject * get_module_state(PyObject *self)
{
return PyLong_FromLong(module_state);
}
在 python (3) 我可以简单地做:
import module
...
state = module.get_module_state()
但是,我想将它公开为一个变量:
import module
state = module.module_state
我查看了 API 中的 PyMemberDef
和 PyGetterSetterDef
,但我对如何使用它们公开变量感到困惑。一般来说,我不希望 python 用户能够修改变量。
这个变量的用途与errno
非常相似,我想让它尽可能透明地可用。
Can modules have properties the same way that objects can? 中的两个主要建议实际上可以非常“轻松”地翻译成 C。
模块级
定义一个名为__getattr__
。这需要Python 3.7。您只需使用 the normal C API mechanism,PyMethodDef
.__getattr__
的函数这个函数会做这样的事情:
if (PyUnicode_CompareWithASCIIString(arg, "name") == 0) { return PyLong_FromLong(your_variable); } else { PyErr_SetObject(PyExc_AttributeError, arg); return NULL; }
请注意,限制(我认为您可以接受)是该变量将是只读的,因为没有等效的模块
__setattr__
。使用 class 代替模块。这可以是在 C 中定义的 class,
PyMemberDef
将 C 变量公开为 属性.这可能最适合子模块(例如
main_mod.submod
)。这样主模块可以将您的 class 实例添加到sys.modules
中,例如:PyObject *sys_modules = PySys_GetObject("modules"); PyDict_SetItemString(sys_modules, "main_mod.submod", instance);
我认为这种方法可能比第一种方法麻烦得多,但它可以在 C 中使用。