python将对象拉入本地作用域以进行读取访问

python将对象拉入本地作用域以进行读取访问,python,c++,boost,scope,boost-python,Python,C++,Boost,Scope,Boost Python,我使用Posi.python向Python导出C++函数。在这个函数中,我希望访问本地堆栈框架上的Python对象,而不需要在Python端访问这个对象 示例:我有一个C++对象 x,还有一个C++函数 cppFung导出到Python,然后遵循代码, x = X() def fun(): cppfun() # no explicit access to x 在cppfun内部,我可以使用PyEval\u GetLocals访问本地堆栈帧,但由于 Python端不包含对x的任

我使用Posi.python向Python导出C++函数。在这个函数中,我希望访问本地堆栈框架上的Python对象,而不需要在Python端访问这个对象

示例:我有一个C++对象<代码> x<代码>,还有一个C++函数<代码> cppFung导出到Python,然后遵循代码,

x = X()

def fun():
    cppfun()
    # no explicit access to x
cppfun
内部,我可以使用
PyEval\u GetLocals
访问本地堆栈帧,但由于 Python端不包含对
x
的任何引用,此对象将不在该本地堆栈帧中(类似地,如果您
print(locals())
fun
中,则
x
将不存在,除非您添加对它的引用,例如
print(x)

是否有任何方法可以访问
x
内部
cppfun
,也就是说,我是否可以强制Python将其拉入
locals
,而不访问Python内部的
fun
?我试着简单地运行
boost::python::eval(“x”)
,但运行的范围也不正确


添加:因此我不想让外部框架中的
x
内部可写,有趣的
或类似的东西(我知道这是不可能的);这个问题纯粹是关于如何从外部框架获得对变量的读取访问,而不必在Python端访问它。

可以通过使用访问外部范围,它返回当前执行框架中全局变量的字典。它非常类似于Python内置函数,该函数返回定义函数的模块的全局符号表。但是,在标准模块和扩展模块之间,帧堆栈的处理略有不同。对于扩展模块,当前执行帧是调用者,因此
PyEval_GetGlobals()
将返回调用者模块的全局符号,而不是扩展模块的全局符号

或者,可以通过获取当前帧的句柄,然后遍历堆栈,检查每个帧的本地(
f_local
)和全局(
f_global
)字典


下面是一个完整的最小示例,演示了这两种技术以及它们之间的细微差异。在本例中,
get\u global()
将使用
PyEval\u GetGlobals()
,而
search\u stack\u locals()
将检查堆栈中每个帧的本地字典

#包括
名称空间详细信息{
///@brief返回全局变量的句柄。如果找不到句柄,则
///没有人返回。
boost::python::object get_global(std::string name)
{
//借用本地词典中的引用来创建句柄。
//如果PyEval_GetGlobals()返回NULL,那么Boost.Python将抛出。
名称空间python=boost::python;
python::dict globals(python::借用(PyEval_GetGlobals());
返回globals.get(name);
}
///@在调用堆栈中搜索变量。如果找到,则
///对象返回。否则,无。
boost::python::对象搜索\堆栈\局部变量(std::字符串名称)
{
//获取当前帧的句柄。
名称空间python=boost::python;
python::对象框架(python::借用)(
重新解释cast(PyEval_GetFrame());
//迭代堆栈的帧,直到找到变量为止
//或者堆栈已耗尽。
while(框架)
{
//如果当前帧具有所需的变量,则返回该变量。
python::dict locals(frame.attr(“f_locals”);
if(本地人。有_键(名称))
{
返回locals.get(name);
}
//向上移动堆栈。
frame=frame.attr(“f_back”);
}
//一无所获
返回python::object();
}
}//名称空间详细信息
///@brief-Mockup函数演示如何查找非局部变量。
boost::python::object cppfun(std::string name)
{
返回boost::python::make_tuple(
detail::get_global(名称),detail::search_stack_locals(名称));
}
BOOST_PYTHON_模块(示例)
{
名称空间python=boost::python;
python::def(“cppfun”和&cppfun);
}
spam.py
中:

导入示例
x='spam.global.x'
y='spam.global.y'
def inner():
对于('x','y','z')中的名称:
打印名称,例如.cppfun(名称)
def outer():
x='spam.outer.x'
内()
互动使用:

>x='main.global.x'
>>>y='main.global.y'
>>>z='main.global.z'
>>>导入垃圾邮件
>>>spam.outer()
x('spam.global.x','spam.outer.x')
y('spam.global.y','main.global.y')
z(无,'main.global.z')
请注意,当使用
PyEval\u GetGlobals()
时,
示例
扩展模块使用调用方模块的全局符号表(
垃圾邮件
)。在解释器的主命名空间中声明的globals只有在遍历堆栈时才能找到