揭露C ++函数,使用Boost.Python的是返回指针 [英] Exposing C++ functions, that return pointer using Boost.Python

查看:1790
本文介绍了揭露C ++函数,使用Boost.Python的是返回指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Boost.Python的,露出下面的C ++函数的Python:

I want to expose the following C++ function to Python using Boost.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。

When I try to compile this library the error occurs due to (it's my guess) Boost.Python don't know, how to convert int* to PyObject.

我觉得什么需要做的是定义转换结构,是这样的:

I think what needs to be done is to define conversion structure, something like this:

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

和它传递到BOOST_PYTHON_MODULE声明:

And pass it to the BOOST_PYTHON_MODULE declaration:

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

但是,它也无法工作。我不能找到有关如何的功能,即返回指针应该如何处理的任何信息。

But it also doesn't work. And I can't find any information about how the functions, that return pointers should be handled.

有谁可以帮忙吗?

推荐答案

在短,不能直接暴露函数返回为int * 与Boost.Python的,因为有在Python整数给出任何有意义的相应类型是不可改变的。

In short, one cannot directly expose a function returning int* with Boost.Python, as there is no meaningful corresponding type in Python given integers are immutable.


  • 如果目标是一个数字返回到Python,然后返回值 INT 。这可能需要使用辅助功能,以适应传统的API。

  • 如果目标是返回一个指向一个新的-EX pression分配的对象,那么对象必须是类或联合,和函数必须以具体的政策会接触到注明所有权responsabilities。

  • If the goal is to return a number to Python, then return int by value. This may require using an auxiliary function to adapt legacy APIs.
  • If the goal is to return a pointer to an object allocated with a new-expression, then the object must be a class or union, and the function must be exposed with specific policies to indicate ownership responsabilities.

而不是present最终的解决方案立即,我想花时间来逐步的编译器错误。随着Boost.Python的,有时是pre-C ++ 11静态断言是用来提供编译器的消息的指令。不幸的是,它可以是一个有点难以找到他们之间的沉重的模板。

Rather than present the final solution immediately, I would like to take the time to step through the compiler errors. With Boost.Python, sometimes pre-C++11 static assertions are used to provide instructions in the compiler messages. Unfortunately, it can be a bit difficult to find them amongst the heavy templates.

以下code:

#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);
}

在生产铛以下相关的输出,用粗体突出重要的细节:

produces the following relevant output in clang, with the important details accentuated in bold:


.../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的是通知我们, 提高::蟒蛇:: return_value_policy 需要用于返回函数指定为int * 。有 ResultConverterGenerators 的各种型号。很多时候,策略被用来控制返回对象的所有权或寿命语义。正如原code的作用是直接返回一个新的指针到Python的的 的boost ::蟒蛇:: manage_new_object 如果主叫方预计需要删除的对象的责任是合适的。

Boost.Python is informing us that a boost::python::return_value_policy needs to be specified for functions returning int*. There are various models of ResultConverterGenerators. Often times the policies are used to control the ownership or lifetime semantics of the returned object. As the function in the original code is returning a new pointer directly to Python, the boost::python::manage_new_object is appropriate if the caller is expected to take responsibility for deleting the object.

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

Specifying a policy for object management still fails:

#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>());
}

产生以下相关的输出:

produces the following relevant output:


.../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的函数返回的必须是联盟。对于为int * ,最合适的解决方案是按值传递通过Boost.Python的层何时返回 INT 。然而,对于完整性,如下所示:

In this case, Boost.Python is informing us that the object returned from a function with a managed_new_object ResultConverterGenerator must be either a class or union. For an int*, the most appropriate solution is to return the int by value when passing through the Boost.Python layer. However, for completeness, below demonstrates:


  • 使用辅助功能,以适应遗留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)

这篇关于揭露C ++函数,使用Boost.Python的是返回指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆