python - 如何将 C 变量作为变量公开给 Python?
问题描述
假设在一个用 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
,我想让它尽可能透明地可用。
解决方案
模块中的两个主要建议可以像对象一样具有属性吗?实际上可以很“容易”地翻译成 C。
模块级
__getattr__
. 这需要 Python 3.7。您只需定义一个__getattr__
使用普通 C API 机制调用的函数,PyMethodDef
.此功能将执行以下操作:
if (PyUnicode_CompareWithASCIIString(arg, "name") == 0) { return PyLong_FromLong(your_variable); } else { PyErr_SetObject(PyExc_AttributeError, arg); return NULL; }
请注意,限制(我认为您可以接受)是该变量将是只读的,因为没有等效的模块
__setattr__
。使用类而不是模块。这可以是在 C 中定义的类,
PyMemberDef
将 C 变量作为属性公开。这可能最适合子模块(例如
main_mod.submod
)。这样,主模块可以将您的类实例添加到以下内容sys.modules
:PyObject *sys_modules = PySys_GetObject("modules"); PyDict_SetItemString(sys_modules, "main_mod.submod", instance);
我认为这种方式可能比第一种选择麻烦得多,但它可以在 C 中工作。
推荐阅读
- mysql - 如何获取订单总金额和发票数量?
- python - Pygame 中使用的图像文件出现在“最近使用”文件夹中
- wpf - 仅 UI 元素的全球化
- wildfly - OpenId django-oidc-provider 使用 keycloak 适配器在 Wildfly 中进行身份验证 - 无法解析 JWT
- javascript - 删除 iframe 中的 header.html
- jenkins - 如何自动检查更新的 Jenkins 插件版本?
- html - 如何在不破坏固定元素定位的情况下使用 css 过滤器创建暗模式?
- linux - 循环连续粘贴到文件而不覆盖
- python - 如何处理库 API 的更改以避免破坏 Python 中的用户代码
- selenium - 访问工具提示 selenium python 后面的元素文本