问题描述:

How to define in C++ using Boost Python function which is functionally equivalent to Python function

def test():

return list

网友答案:

While Boost.Python TypeWrappers provide a convenient way to instantiate objects for certain built-in Python types, Boost.Python does not provide direct support for first-class objects themselves. However, one can return the first-class objects through Boost.Python via the appropriate PyTypeObject object in the Python/C API.

In this particular case, the Python list type is PyList_Type within the Python/C API. The Python code:

def test():
    return list

is equivalent to the following C++ Boost.Python code:

boost::python::object test()
{
  namespace python = boost::python;
  python::handle<PyTypeObject> handle(python::borrowed(&PyList_Type));
  return python::object(handle);
}

When mixing the Python/C API and higher-level Boost.Python code, one must use a boost::python::handle to construct a boost::python::object from a PyObject object or an object with a derived (layout-compatible) type, such as PyTypeObject. A handle is essentially a smart-pointer responsible for handling Python reference counting. The handle's destructor will always decrement the associated Python object's reference count. Therefore, care must be given when constructing the handle, as one must know whether or not the handle needs to increment the reference count or if it has already been incremented. If the reference count has not already been incremented, such as in the above code, then one must pass the return type of boost::python::borrowed() to handle's constructor. For more details, consider reading this link.


Here is a complete example:

#include <boost/python.hpp>

boost::python::object test()
{
  namespace python = boost::python;
  python::handle<PyTypeObject> handle(python::borrowed(&PyList_Type));
  return python::object(handle);
}

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

Interactive usage:

>>> import example
>>> assert(example.test() is list)
>>> t = example.test()
>>> assert(t((1, 2, 3)) == [1, 2, 3])
>>> assert(t((1, 2, 3)) != (1, 2, 3))
>>> del t
>>> from sys import getrefcount # test for proper reference counting
>>> n = getrefcount(list)
>>> t = example.test()
>>> assert(n + 1 == getrefcount(list))
>>> del t
>>> assert(n == getrefcount(list))
相关阅读:
Top