Differences between revisions 1 and 6 (spanning 5 versions)
Revision 1 as of 2002-11-20 19:28:20
Size: 493
Editor: MikeRovner
Comment:
Revision 6 as of 2003-01-17 21:17:34
Size: 3523
Editor: MikeRovner
Comment: staticmethod fix
Deletions are marked like this. Additions are marked like this.
Line 16: Line 16:
=== static class functions ===
It's likely to be in 1.30 release.

Meanwhile you should do something which mirrors pure Python:
{{{
class foo(object):
    def f(x,y):
        return x*y
    f = staticmethod(f)
}}}
So in C++, it would be something like:
{{{
   class_<foo>("foo")
        .def("f", &foo::f)
        .staticmethod("f") // **
        ;
}}}
Where the marked line would be implemented something like this:
{{{
   self& staticmethod(char const* name)
   {
        dict d(handle<>(borrowed(downcast<PyTypeObject>(this->ptr())->tp_dict)));
        object method = (object)(d[name]);
        this->attr(name) = object(handle<>(
             PyStaticMethod_New( callable_check(method.ptr()) )
            ));
   }
}}}
To create overloaded staticmethods in python, you overload first, then you make it static.
Line 17: Line 47:
==== at module creation time ====
Line 27: Line 58:
==== at run-time ====
Use a function:
{{{
template <class T>
void set(const std::string& name, const T& value) {
  interpreter()->mainmodule()[name] = value;
}
}}}
Line 28: Line 67:
Note:: ''interpreter()'' is to be added about now. [[Date]]
=== mutable C++ object ===
Perhaps you'd like the resulting Python object to contain a raw
pointer to the argument? In that case, the caveat is that if the
lifetime of the C++ object ends before that of the Python object, that
pointer will dangle and using the Python object may cause a crash.

There is a way to do that, but it's more convoluted than it should be:
{{{
  template <class T>
  T& identity(T& x)
  {
      return x;
  }

  template <class T>
  object get_object_reference(T& x)
  {
      // build a function object around identity
      object f
          = make_function(
                  &identity<T>, return_value_policy<reference_existing_object>());

      // and call
      return f(x);
  }
}}}

=== "Raw" function ===
''I want to write in python:''
    {{{
    def function( *args ):
        # Mess arount with elements of args.
    }}}

You can make one with the
library's implementation details. Be warned that these interfaces may
change, but hopefully we'll have an "official" interface for what you
want to do by then.
{{{
python::objects::function_object(
    f // must be py_function compatible
    , 0, std::numeric_limits<unsigned>::max() // arity range
    , python::detail::keyword_range()); // no keywords
}}}
will create a Python callable object.

'''f''' is any function pointer, function reference, or function object
which can be invoked with two Py``Object* arguments and returns
something convertible to a Py``Object*.

You can add this to your module namespace with:
{{{
scope().attr("name") = function_object(f, ... );
}}}
Now you can also
{{{
class_<foo>("foo")
    .def("bar",function_object(f, ... ) );
}}}
aswell, but '''''not'''''
{{{
function_object bar(f, ... );
...
class_<foo>("foo")
    .def("bar",bar);
}}}
because function_object is a function, not a class.

How to expose...

static class data members

object x_class 
    = class_<X>("X") 
         .def( ... ) 
         ... 
         ; 
 
x_class.attr("fu") = X::fu; 
x_class.attr("bar") = X::bar; 
... 

static class functions

It's likely to be in 1.30 release.

Meanwhile you should do something which mirrors pure Python:

class foo(object):
    def f(x,y):
        return x*y
    f = staticmethod(f)

So in C++, it would be something like:

   class_<foo>("foo")
        .def("f", &foo::f)
        .staticmethod("f")  // **
        ;

Where the marked line would be implemented something like this:

   self& staticmethod(char const* name)
   {
        dict d(handle<>(borrowed(downcast<PyTypeObject>(this->ptr())->tp_dict))); 
        object method = (object)(d[name]); 
        this->attr(name) = object(handle<>(
             PyStaticMethod_New( callable_check(method.ptr()) ) 
            ));
   }

To create overloaded staticmethods in python, you overload first, then you make it static.

module level objects

at module creation time

First, create those objects like

object class_X = class_<X>("X");
object x = class_X();

Second, expose them:

scope().attr("x") = x; // injects x into current scope

By default current scope is module.

at run-time

Use a function:

template <class T>
void set(const std::string& name, const T& value) {
  interpreter()->mainmodule()[name] = value;
}

Note:: interpreter() is to be added about now. Date

mutable C++ object

Perhaps you'd like the resulting Python object to contain a raw pointer to the argument? In that case, the caveat is that if the lifetime of the C++ object ends before that of the Python object, that pointer will dangle and using the Python object may cause a crash.

There is a way to do that, but it's more convoluted than it should be:

  template <class T>
  T& identity(T& x)
  {
      return x;
  }

  template <class T>
  object get_object_reference(T& x)
  {
      // build a function object around identity
      object f
          = make_function(
                  &identity<T>, return_value_policy<reference_existing_object>());

      // and call
      return f(x);
  }

"Raw" function

I want to write in python:

  •     def function( *args ):
            # Mess arount with elements of args.

You can make one with the library's implementation details. Be warned that these interfaces may change, but hopefully we'll have an "official" interface for what you want to do by then.

python::objects::function_object(
    f                       // must be py_function compatible
    , 0, std::numeric_limits<unsigned>::max()  // arity range
    , python::detail::keyword_range());        // no keywords

will create a Python callable object.

f is any function pointer, function reference, or function object which can be invoked with two PyObject* arguments and returns something convertible to a PyObject*.

You can add this to your module namespace with:

scope().attr("name") = function_object(f, ... );

Now you can also

class_<foo>("foo")
    .def("bar",function_object(f, ... ) );

aswell, but not

function_object bar(f, ... );
...
class_<foo>("foo")
    .def("bar",bar);

because function_object is a function, not a class.

boost.python/HowTo (last edited 2015-04-21 17:00:36 by HansDembinski)

Unable to edit the page? See the FrontPage for instructions.