为了解决这个问题,我从模块中检索了该类,并给出了它的模块名称和类名称(下面的代码假设该模块尚未加载):
void Model::Visit(const char* mod_name, const char* class_name)
{
PyErr_Clear();
PyObject* mod_name_obj = PyString_FromString(mod_name);
PyObject* class_name_obj = PyString_FromString(class_name);
PyObject* py_module = PyImport_Import(mod_name_obj);
PyObject* err_1 = PyErr_Occurred();
if(err_1)
PyErr_Print();
获得该模块后,我从它的字典中查找该类:
if(py_module)
{
PyObject* py_module_dict = PyModule_GetDict(py_module);
PyObject* py_class = PyDict_GetItem(py_module_dict, class_name_obj);
我通过在 C++ 中实例化 python 类来稍微简化了我的问题,然后创建了我的访问者,最后访问了它:
if(py_class && PyClass_Check(py_class) && PyCallable_Check(py_class))
{
PyObject* inst = PyInstance_New(py_class, 0, 0);
if(inst && PyInstance_Check(inst))
{
IModel::IVisitorPtr py_visitor = new PyModelVisitor(inst);
_model->Visit(py_visitor);
}
}
}
}
访问者有 3 个函数 OnStateBegin()、OnNode() 和 OnStateEnd()。我在 SWIG python 绑定生成器中添加了一个选项,用于生成头文件,以便使用以下命令从外部访问 SWIG 运行时-外部运行时选项 http://swig.org/Doc2.0/SWIGDocumentation.html#Modules_external_run_time,所以我可以用 C++ 创建一个类(下面的 INode*),并将其作为 python OnNode() 成员函数的参数传递给 Python,如下所示(为了简洁,删除了错误检查):
VisitorCtrl OnNode(INode* node)
{
Node* node_impl = new NodeImpl(node);
PyObject* pynode = SWIG_NewPointerObj(node_impl, SWIG_TypeQuery("Node *"), 0);
PyObject* result = PyObject_CallMethodObjArgs(_inst, PyString_FromString("OnNode"), pynode, 0);
long rivis = PyInt_AsLong(result);
return(static_cast<VisitorCtrl>(rivis));
}