我正在使用C API编写一个简单的扩展模块。这是一个测试示例:
#include <Python.h>
#include <structmember.h>
typedef struct {
PyObject_HEAD
int i;
} MyObject;
static PyMemberDef my_members[] = {
{"i", T_INT, offsetof(MyObject, i), READONLY, "Some integer"},
{NULL} /* Sentinel */
};
static int MyType_init(MyObject *self, PyObject *args, PyObject *kwds)
{
char *keywords[] = {"i", NULL};
int i = 0;
if(!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &i)) {
return -1;
}
self->i = i;
return 0;
}
static PyTypeObject MyType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "_my.MyType",
.tp_doc = "Pointless placeholder class",
.tp_basicsize = sizeof(MyObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_init = (initproc)MyType_init,
.tp_members = my_members,
};
static PyModuleDef my_module = {
PyModuleDef_HEAD_INIT,
.m_name = "_my",
.m_doc = "My module is undocumented!",
.m_size = -1,
};
/* Global entry point */
PyMODINIT_FUNC PyInit__my(void)
{
PyObject *m = NULL;
PyExc_MyException = PyErr_NewExceptionWithDoc("_my.MyException",
"Indicates that something went horribly wrong.",
NULL, NULL);
if(PyExc_MyException == NULL) {
return NULL;
}
if(PyType_Ready(&MyType) < 0) {
goto err;
}
if((m = PyModule_Create(&my_module)) == NULL) {
goto err;
}
Py_INCREF(&MyType);
PyModule_AddObject(m, "MyType", (PyObject *)&MyType);
PyModule_AddObject(m, "MyException", (PyObject *)PyExc_MyException);
return m;
err:
Py_CLEAR(PyExc_MyException);
return NULL;
}
此模块包含一个类MyType
和一个例外MyException
。此模块的目的是为使用Python编写的一些其他代码提供基本功能。我希望能够做到这样的事情:
my.py
from _my import *
class MyType(MyType):
def __init__(i=0):
raise MyException
显然这个例子非常人为。我只想说明如何使用my
扩展名中的名称。现在导入工作正常,根据rule:
如果未定义
__all__
,则公共名称集包括在模块命名空间中找到的所有名称,这些名称不以下划线字符('_'
)开头。
但是,我希望有更好的控制水平。到目前为止,我能够想到的是手动向模块添加__all__
属性:
PyObject *all = NULL;
...
all = Py_BuildValue("[s, s]", "MyType", "MyException");
if(all == NULL) {
goto err;
}
PyModule_AddObject(m, "__all__", all);
...
err:
...
Py_CLEAR(all);
这看起来有点笨重。 C API中是否有一个函数用于为模块定义__all__
的内部等效项?
我认为可能存在内部等效的部分原因是__all__
毕竟是dunder属性。