boostpython:使用return\u internal\u引用将参数的生存期绑定到返回值

boostpython:使用return\u internal\u引用将参数的生存期绑定到返回值,python,c++,c++11,boost,boost-python,Python,C++,C++11,Boost,Boost Python,我开始学习使用boostpython,并提出了一个新手问题 我想编写一个函数,将其参数的生存期与其结果联系起来,这样当我调用r=func(a)时,如果我仍然有r的引用,则参数a将永远不会被销毁。文档建议对此类请求使用return\u internal\u referencecall策略。但这是否要求r作为a的内部参考,正如名称所示 在下面的(过于简化的)示例中,假设我想将输入数组a的生存期与生成的lambda函数联系起来,该函数不是输入a的内部引用 #include <functional

我开始学习使用boostpython,并提出了一个新手问题

我想编写一个函数,将其参数的生存期与其结果联系起来,这样当我调用
r=func(a)
时,如果我仍然有
r
的引用,则参数
a
将永远不会被销毁。文档建议对此类请求使用
return\u internal\u reference
call策略。但这是否要求
r
作为
a
的内部参考,正如名称所示

在下面的(过于简化的)示例中,假设我想将输入数组
a
的生存期与生成的lambda函数联系起来,该函数不是输入
a
的内部引用

#include <functional>
#include <boost/python.hpp>
#include <boost/python/return_internal_reference.hpp>

using namespace std;
using namespace boost::python;

function<float(int)> func(const float* a) {
  return [=](int n) { return a[n]; };
}

BOOST_PYTHON_MODULE(test) {
  def("func", func, return_internal_reference<1>());
}
当我试图编译上面的代码时,下面列出了一大堆错误,但是如果我删除
return\u internal\u reference()
call策略,代码编译成功

我很确定我使用这个呼叫策略是错误的,但不确定如何使它正确。任何指针都将受到高度赞赏。非常感谢

$ g++ -std=c++11 -shared Test.cc -I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -L/opt/local/lib -lboost_python-mt -lpython2.7 -o test.so
In file included from /opt/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0,
                 from /opt/local/include/boost/python/detail/invoke.hpp:63,
                 from /opt/local/include/boost/python/detail/caller.hpp:16,
                 from /opt/local/include/boost/python/object/function_handle.hpp:8,
                 from /opt/local/include/boost/python/converter/arg_to_python.hpp:19,
                 from /opt/local/include/boost/python/call.hpp:15,
                 from /opt/local/include/boost/python/object_core.hpp:14,
                 from /opt/local/include/boost/python/args.hpp:25,
                 from /opt/local/include/boost/python.hpp:11,
                 from Test.cc:2:
/opt/local/include/boost/python/detail/invoke.hpp: In instantiation of 'PyObject* boost::python::detail::invoke(boost::python::detail::invoke_tag_<false, false>, const RC&, F&, AC0&) [with RC = boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >; F = std::function<float(int)> (*)(const float*); AC0 = boost::python::arg_from_python<const float*>; PyObject = _object]':
/opt/local/include/boost/python/detail/caller.hpp:223:13:   required from 'PyObject* boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = std::function<float(int)> (*)(const float*); Policies = boost::python::return_internal_reference<>; Sig = boost::mpl::vector2<std::function<float(int)>, const float*>; PyObject = _object]'
/opt/local/include/boost/python/object/py_function.hpp:38:33:   required from 'PyObject* boost::python::objects::caller_py_function_impl<Caller>::operator()(PyObject*, PyObject*) [with Caller = boost::python::detail::caller<std::function<float(int)> (*)(const float*), boost::python::return_internal_reference<>, boost::mpl::vector2<std::function<float(int)>, const float*> >; PyObject = _object]'
Test.cc:14:1:   required from here
/opt/local/include/boost/python/detail/invoke.hpp:75:82: error: no match for call to '(const boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >) (std::function<float(int)>)'
     return rc(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ));
                                                                                  ^
In file included from /opt/local/include/boost/python/object/function_handle.hpp:8:0,
                 from /opt/local/include/boost/python/converter/arg_to_python.hpp:19,
                 from /opt/local/include/boost/python/call.hpp:15,
                 from /opt/local/include/boost/python/object_core.hpp:14,
                 from /opt/local/include/boost/python/args.hpp:25,
                 from /opt/local/include/boost/python.hpp:11,
                 from Test.cc:2:
/opt/local/include/boost/python/detail/caller.hpp: In instantiation of 'static const PyTypeObject* boost::python::detail::converter_target_type<ResultConverter>::get_pytype() [with ResultConverter = boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >; PyTypeObject = _typeobject]':
/opt/local/include/boost/python/detail/caller.hpp:240:19:   required from 'static boost::python::detail::py_func_sig_info boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::signature() [with F = std::function<float(int)> (*)(const float*); Policies = boost::python::return_internal_reference<>; Sig = boost::mpl::vector2<std::function<float(int)>, const float*>]'
/opt/local/include/boost/python/object/py_function.hpp:48:35:   required from 'boost::python::detail::py_func_sig_info boost::python::objects::caller_py_function_impl<Caller>::signature() const [with Caller = boost::python::detail::caller<std::function<float(int)> (*)(const float*), boost::python::return_internal_reference<>, boost::mpl::vector2<std::function<float(int)>, const float*> >]'
Test.cc:14:1:   required from here
/opt/local/include/boost/python/detail/caller.hpp:102:109: error: 'struct boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >' has no member named 'get_pytype'
         return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype();
                                                                                                             ^
$g++-std=c++11-shared Test.cc-I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7-L/opt/local/lib-lboost\u Python-mt-lpython2.7-o Test.so
在/opt/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0中包含的文件中,
从/opt/local/include/boost/python/detail/invoke.hpp:63,
从/opt/local/include/boost/python/detail/caller.hpp:16,
从/opt/local/include/boost/python/object/function_handle.hpp:8,
从/opt/local/include/boost/python/converter/arg_到_python.hpp:19,
从/opt/local/include/boost/python/call.hpp:15,
从/opt/local/include/boost/python/object_core.hpp:14,
从/opt/local/include/boost/python/args.hpp:25,
从/opt/local/include/boost/python.hpp:11,
来自测试。cc:2:
/opt/local/include/boost/python/detail/invoke.hpp:PyObject*boost::python::detail::invoke(boost::python::detail::invoke\u tag,const RC&,F&,AC0&)实例化[with RC=boost::python::detail::reference\u现有的\u对象需要\u指针\u或\u reference\u返回类型;F=std::function(*)(const float*);AC0=boost::python::arg_from_python;PyObject=_object]':
/opt/local/include/boost/python/detail/caller.hpp:223:13:必须来自'PyObject*boost::python::detail::caller_arity::impl::operator()(PyObject*,PyObject*)[with F=std::function(*)(const float*);polics=boost::python::return_internal_reference;Sig=boost::mpl::vector2;PyObject=\u object]'
/opt/local/include/boost/python/object/py_function.hpp:38:33:必须来自“PyObject*boost::python::objects::caller_py_function\u impl::operator()(PyObject*,PyObject*)[with caller=boost::python::detail::caller;PyObject=\u object]”
测试。cc:14:1:从这里开始需要
/opt/local/include/boost/python/detail/invoke.hpp:75:82:错误:调用“(const boost::python::detail::reference_现有_对象_需要_指针_或_引用_返回_类型)(std::function)”不匹配
返回rc(f(BOOST_PP_ENUM_BINARY_PARAMS_Z(1,N,ac,()BOOST_PP_INTERCEPT));
^
在/opt/local/include/boost/python/object/function_handle.hpp:8:0中包含的文件中,
从/opt/local/include/boost/python/converter/arg_到_python.hpp:19,
从/opt/local/include/boost/python/call.hpp:15,
从/opt/local/include/boost/python/object_core.hpp:14,
从/opt/local/include/boost/python/args.hpp:25,
从/opt/local/include/boost/python.hpp:11,
来自测试。cc:2:
/opt/local/include/boost/python/detail/caller.hpp:static const PyTypeObject*boost::python::detail::converter\u target\u type::get\u pytype()[with ResultConverter=boost::python::detail::reference\u现有的\u对象\u需要\u指针\u或\u reference\u返回\u type;PyTypeObject=\u typeobject]:
/opt/local/include/boost/python/detail/caller.hpp:240:19:static boost::python::detail::py\u func\u sig\u info boost::python::detail::caller\u arity::impl::signature()[with F=std::function(*)(const float*);Policies=boost::python::return\u internal\u reference;sig=boost::mpl::vector2]'
/opt/local/include/boost/python/object/py_function.hpp:48:35:来自“boost::python::detail::py_func_sig_info boost::python::objects::caller_py_function_impl::signature()const[with caller=boost::python::detail::caller]'
测试。cc:14:1:从这里开始需要
/opt/local/include/boost/python/detail/caller.hpp:102:109:错误:“struct boost::python::detail::reference_现有的_对象_需要_指针_或_reference_return_类型”没有名为“get_pytype”的成员
返回create_result_converter((PyObject*)0,(ResultConverter*)0,(ResultConverter*)0;
^
考虑使用。此策略允许返回类型按值返回,同时仍将另一个对象的生存期延长至至少与返回对象的生存期相同

BOOST\u PYTHON\u模块(测试){
def(“func”,func,带有监护权和监护权);
}

如文档中所述,返回的对象引用现有的内部对象:

return\u internal\u reference
[…]允许安全返回指向内部持有的对象[…]的指针和引用,而无需复制引用对象

本文档还简要介绍了它与保管人和后调用的使用。总之,
return\u internal\u reference
对公开的函数有两个值得注意的影响:

  • 那个人回来了
    $ g++ -std=c++11 -shared Test.cc -I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -L/opt/local/lib -lboost_python-mt -lpython2.7 -o test.so
    In file included from /opt/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0,
                     from /opt/local/include/boost/python/detail/invoke.hpp:63,
                     from /opt/local/include/boost/python/detail/caller.hpp:16,
                     from /opt/local/include/boost/python/object/function_handle.hpp:8,
                     from /opt/local/include/boost/python/converter/arg_to_python.hpp:19,
                     from /opt/local/include/boost/python/call.hpp:15,
                     from /opt/local/include/boost/python/object_core.hpp:14,
                     from /opt/local/include/boost/python/args.hpp:25,
                     from /opt/local/include/boost/python.hpp:11,
                     from Test.cc:2:
    /opt/local/include/boost/python/detail/invoke.hpp: In instantiation of 'PyObject* boost::python::detail::invoke(boost::python::detail::invoke_tag_<false, false>, const RC&, F&, AC0&) [with RC = boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >; F = std::function<float(int)> (*)(const float*); AC0 = boost::python::arg_from_python<const float*>; PyObject = _object]':
    /opt/local/include/boost/python/detail/caller.hpp:223:13:   required from 'PyObject* boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = std::function<float(int)> (*)(const float*); Policies = boost::python::return_internal_reference<>; Sig = boost::mpl::vector2<std::function<float(int)>, const float*>; PyObject = _object]'
    /opt/local/include/boost/python/object/py_function.hpp:38:33:   required from 'PyObject* boost::python::objects::caller_py_function_impl<Caller>::operator()(PyObject*, PyObject*) [with Caller = boost::python::detail::caller<std::function<float(int)> (*)(const float*), boost::python::return_internal_reference<>, boost::mpl::vector2<std::function<float(int)>, const float*> >; PyObject = _object]'
    Test.cc:14:1:   required from here
    /opt/local/include/boost/python/detail/invoke.hpp:75:82: error: no match for call to '(const boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >) (std::function<float(int)>)'
         return rc(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ));
                                                                                      ^
    In file included from /opt/local/include/boost/python/object/function_handle.hpp:8:0,
                     from /opt/local/include/boost/python/converter/arg_to_python.hpp:19,
                     from /opt/local/include/boost/python/call.hpp:15,
                     from /opt/local/include/boost/python/object_core.hpp:14,
                     from /opt/local/include/boost/python/args.hpp:25,
                     from /opt/local/include/boost/python.hpp:11,
                     from Test.cc:2:
    /opt/local/include/boost/python/detail/caller.hpp: In instantiation of 'static const PyTypeObject* boost::python::detail::converter_target_type<ResultConverter>::get_pytype() [with ResultConverter = boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >; PyTypeObject = _typeobject]':
    /opt/local/include/boost/python/detail/caller.hpp:240:19:   required from 'static boost::python::detail::py_func_sig_info boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::signature() [with F = std::function<float(int)> (*)(const float*); Policies = boost::python::return_internal_reference<>; Sig = boost::mpl::vector2<std::function<float(int)>, const float*>]'
    /opt/local/include/boost/python/object/py_function.hpp:48:35:   required from 'boost::python::detail::py_func_sig_info boost::python::objects::caller_py_function_impl<Caller>::signature() const [with Caller = boost::python::detail::caller<std::function<float(int)> (*)(const float*), boost::python::return_internal_reference<>, boost::mpl::vector2<std::function<float(int)>, const float*> >]'
    Test.cc:14:1:   required from here
    /opt/local/include/boost/python/detail/caller.hpp:102:109: error: 'struct boost::python::detail::reference_existing_object_requires_a_pointer_or_reference_return_type<std::function<float(int)> >' has no member named 'get_pytype'
             return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype();
                                                                                                                 ^
    
    struct boost::python::detail:: reference_existing_object_requires_a_pointer_or_reference_return_type