在StackOverflow上学到的。
我们知道,Python中有PyObject_GetAttrString、PyObject_SetAttrString、PyImport_ImportModule、PyImport_AddModule等API函数,但这些只能调用外部Python脚本。如何调用PyRun_SimpleString中创造的变量呢?
先介绍一个东西:
__main__
这个东西并不是
if __name__ == '__main__':
pass
中的__main__,而是所有当前文件中变量和函数的“上级”。
例如:
>>> class a:
... pass
...
>>> s = a()
>>> type(s)
<class '__main__.a'>
所以,所谓PyRun_SimpleString中定义的变量/函数其实是__main__模块的属性而已。换言之,我们所写的"a = 0",其实是"__main__.a = 0"。
这不就可以为所欲为了吗?
下面的代码中我定义变量a = 0,并获取它的PyObject*指针。
PyRun_SimpleString("a = 0");
PyObject* Py_main = PyImport_AddModule("__main__"); // 得到__main__模块对应的指针
PyObject* Py_a = PyObject_GetAttrString(Py_main, "a");
这样就可以用C语言的API对a进行操作了。
同样,也可以向__main__添加属性以声明变量(下面的代码相当于"var = 11"):
PyObject* Py_var = Py_BuildValue("i"/*i:Integer*/, 11);
PyObject_SetAttrString(Py_main/*刚才得到的*/, "var", Py_var);
这样执行PyRun_SimpleString时就可以愉快地调用刚才定义的变量var了(有关Py_BuildValue请参考解析参数并构建值变量 — Python 3.10.2 文档)
另外,PyRun_SimpleString可以一次运行多个语句!(我一开始把Simple看成Single了