我正在开发一个接口,以便Python程序可以调用现有的C ++库。如果我理解正确,那么这个接口(和C ++库)应该作为模块导入,比如abc
。接口中的类型在接口的C ++端定义为静态变量,并使用以下序列在Python中注册:
void PythonRegistrationData::RegisterType(PyObject* module, PyTypeObject* type)
{
if (type->ob_refcnt < 2)
{
if (type->tp_base != NULL)
RegisterType(module, type->tp_base);
Py_INCREF(type);
if (PyType_Ready(type) != 0)
throw GPython::DummyError();
PyModule_AddObject(module, type->tp_name, as<PyObject>(type));
}
}
(递归是为了确保在派生类之前注册基类。模块已经创建过了。)根据C-API docs,“对于静态分配的类型对象,tp_name字段应该包含一个点。”;因此,我使用tp_name
初始化"abc.MyType"
。当我这样做时,在加载模块后,当我尝试使用该类型时(例如'module' object has no attribute 'MyType'
,之前已经完成x = abc.MyType()
),我得到import abc
。如果我只使用"MyType"
,它似乎有效,但这似乎与官方文档和教程中的示例相矛盾。
那么tp_name
字段的确切含义是什么,它应该包含什么?我没有把模块名称放在里面的效果是什么?
答案 0 :(得分:4)
通过
PyModule_AddObject(module, type->tp_name, as<PyObject>(type));
您正在使用“abc.MyType”作为属性名称将类型添加到模块(这意味着设置属性)。这意味着如果您想在getattr(abc, 'abc.MyType')
模块上访问它,则需要使用abc
访问它(您无法直接访问名称中包含点的属性。)应该将tp_name
设置为“限定”名称(前面有abc.
),您不应该使用tp_name作为属性名称。