Boost logo

Boost :

From: David Abrahams (david.abrahams_at_[hidden])
Date: 2001-11-26 13:07:59


----- Original Message -----
From: "daniel kottow" <daniel.kottow_at_[hidden]>
To: <boost_at_[hidden]>
Cc: <koethe_at_[hidden]>
Sent: Monday, November 26, 2001 11:29 AM
Subject: Re: [boost] how to get a *real* copy of a boost-python object that
supports virtual function

> hello all,
> my code is running now and i wish to thank people who gave their comments
> on my problem. curiosly enough, or maybe reflecting shortcomings in my
> posing of the question, all three answers were very different. i will try
> to give my own now (based more on the solution that works for me than on a
> profound understanding, but this may occurr frequently to occasional users
> who *just* want to port some code from c++ to python).
> in short, the answer to my question is: call the python interpreter to
give
> you one.
> in code (please refer to the earlier posting for more code):

> /********** first we need some helpers to call/register a python func
> ***********/
> /**** this function gives us a new object from the user-derived python
> class **********/
>
> PyObject* PyGAGenome::newPythonUserGenome() const {
> PyObject *arglist, *result;
> arglist = Py_BuildValue("()"); file://python constructor takes no args
> result = PyEval_CallObject(pyFuncNewGenome, arglist);
> Py_DECREF(arglist);
> return result;

or, more simply:

return boost::python::callback<PyObject*>::call(pyFuncNewGenome);

> }

What is pyFuncNewGenome?

> void PyGAGenome::registerNewGenome(PyObject *args)
> {
> pyFuncNewGenome = args; /* Remember new callback */
> }
>
> /**************** now clone may be implemented like this
> *********************/
>
> GAGenome * PyGAGenome::clone(GAGenome::CloneMethod) const {

What is the argument for, above?

> cout << "PyGAGenome::clone()\n";
>
> PyObject *userGenome;
> userGenome = newPythonUserGenome();
>
> // use from_python to get a PyGAGenome *
> PyGAGenome *pg;
> pg = BOOST_PYTHON_CONVERSION::from_python(userGenome,
> python::type<PyGAGenome*>());
>
> return (GAGenome *)pg;
> }

Who is managing the reference-count on the object referred to by userGenome?
I think you only have a valid pointer on exit from this routine because
you're leaking the python object which owns *pg.

>
> /************** copy needs no change, since it doesnt create objects
> **************/
>
> in PYTHON we then have (here PyGAGenome is called simply Genome):
>
> def newExampleGenome():
> return ExampleGenome()

You don't need the above function; ExampleGenome is a callable object which
works exactly the same way.

> class ExampleGenome(Genome):
> def __init__(self):
> self.width = 4
> self.lower = 0
> self.upper = 1
> self.step = 0.1
> Genome.__init__(self, self.width, self.lower, self.upper,
> self.step)
> self.registerNewGenome(newExampleGenome)
> def objective(self):
> d = subtract(self.genes() , [0.1, 0.2, 0.3, 0.4])
> r = sum(multiply(d,d))
> return self.width - r
>
> so, indeed, i didnt have to worry about the PyGAGenome_Callback wrapper
> class.
> one hairy thing, and this may also help phil with from_python() is the
fact
> that you have to "provide" the from_python method by defining the
following
> *before* calling from_python:
>
> struct PyGAGenomeClass
> : python::class_builder<PyGAGenome, PyGAGenome_Callback>
> { PyGAGenomePythonClass(python::module_builder&); };
>
> (i found this trick in comprehensive.hpp)
>
> i hope this may help some lost souls like myself...
>
> BTW,
> i think boost:python is a great enhancement as far as i can reach it.
> its just pretty hard to reach.

We're working on that. Expect improvements over the next 6 months.

BTW, I am still finding what you're trying to accomplish "pretty hard to
reach". Are you just saying that you want to create an instance of some
arbitrary Python type from C++? In that case, you could simply wrap this
function:

boost::python::ref instantiate_with_no_args(boost::python::ref type)
{
    return boost::python::callback<boost::python::ref>::call(type);
}

I am using boost::python::ref as opposed to PyObject* above in order to deal
with reference-counting issues automatically. Using a PyObject* would be a
wash in the example above, but your example really needs:

  boost::python::ref pyFuncNewGenome;

so that the function object can't disappear before you want to call it.

HTH?

-Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk