繁体   English   中英

公开C ++函数,使用Boost.Python返回指针

[英]Exposing C++ functions, that return pointer using Boost.Python

我想使用Boost.Python将以下C ++函数公开给Python:

int* test1() {
    return new int(42);
}

// Now exposing the function with Boost.Python

BOOST_PYTHON_MODULE(libtest1)
{
    using namespace boost::python;
    def("test1", test1);
}

当我尝试编译这个库时,由于(我的猜测)Boost.Python不知道如何将int *转换为PyObject而发生错误。

我认为需要做的是定义转换结构,如下所示:

template<class T>
struct int_ptr_to_python
{
   static PyObject* convert(int* i_ptr)
   {
        return i_ptr;
   }
};

并将其传递给BOOST_PYTHON_MODULE声明:

BOOST_PYTHON_MODULE(libtest1)
{
    using namespace boost::python;
    def("test1", test1);
    to_python_converter<int*, int_ptr_to_python<int*> >();
}

但它也行不通。 而且我找不到有关如何处理返回指针的函数的任何信息。

有人可以帮忙吗?

简而言之,一个人不能直接暴露一个函数,用Boost.Python返回int* ,因为在Python中没有有意义的相应类型,因为整数是不可变的。

  • 如果目标是将数字返回给Python, int值返回int 这可能需要使用辅助功能来适应传统API。
  • 如果目标是返回指向使用new-expression分配的对象的指针,则该对象必须是类或联合,并且必须使用特定策略公开该函数以指示所有权响应。

我不想立即提出最终解决方案,而是花时间逐步解决编译器错误。 使用Boost.Python,有时使用预C ++ 11静态断言来提供编译器消息中的指令。 不幸的是,在繁重的模板中找到它们可能有点困难。

以下代码:

#include <boost/python.hpp>

int* make_int() { return new int(42); }

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::def("make_int", &make_int);
}

在clang中产生以下相关输出,重要细节以粗体突出显示:

.../boost/python/detail/caller.hpp:102:98: error:
  no member named 'get_pytype' in 'boost::python::detail::
    specify_a_return_value_policy_to_wrap_functions_returning<int*>'
  ...create_result_converter((PyObject*)0, (ResultConverter *)0, 
                             (ResultConverter *)0).g...

Boost.Python告诉我们需要为返回int*函数指定boost::python::return_value_policy ResultConverterGenerators有各种模型。 通常,策略用于控制返回对象的所有权或生命周期语义。 由于原始代码中的函数直接向Python返回一个新指针,因此如果调用者需要负责删除该对象,则boost::python::manage_new_object是合适的。

指定对象管理策略仍然失败:

#include <boost/python.hpp>

int* make_int() { return new int(42); }

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::def("make_int", &make_int,
    python::return_value_policy<python::manage_new_object>());
}

产生以下相关输出:

.../boost/python/object/make_instance.hpp:27:9:
  error: no matching function for call to 'assertion_failed'
    BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >));

在这种情况下,Boost.Python通知我们从具有managed_new_object ResultConverterGenerator的函数返回的对象必须是classunion 对于int* ,最合适的解决方案是在通过Boost.Python层时返回int值。 但是,为了完整性,以下说明:

  • 使用辅助功能来调整遗留API。
  • 如何使用返回指针的工厂函数限制用户定义类型的创建。
#include <boost/python.hpp>

/// Legacy API.
int* make_int() { return new int(42); }

/// Auxiliary function that adapts the legacy API to Python.
int py_make_int()
{
  std::auto_ptr<int> ptr(make_int());
  return *ptr;
}

/// Auxiliary class that adapts the legacy API to Python.
class holder
  : private boost::noncopyable
{
public:
  holder()
    : value_(make_int())
  {}

  int get_value() const     { return *value_; }
  void set_value(int value) { *value_ = value; }

private:
  std::auto_ptr<int> value_;
};

/// Factory function for the holder class.
holder* make_holder()
{
  return new holder();
}

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::def("make_int", &py_make_int);

  python::class_<holder, boost::noncopyable>("Holder", python::no_init)
    .add_property("value",
      python::make_function(&holder::get_value),
      python::make_function(&holder::set_value))
    ;

  python::def("make_holder", &make_holder,
    python::return_value_policy<python::manage_new_object>());
}

互动用法:

>>> import example
>>> assert(42 == example.make_int())
>>> holder = example.Holder()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: This class cannot be instantiated from Python
>>> holder = example.make_holder()
>>> assert(42 == holder.value)
>>> holder.value *= 2
>>> assert(84 == holder.value)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM