[C++-sig] returning PyObject * (unmodified) from embedded python back to c++

Ambrose Kofi Laing aklaing at gmail.com
Mon Mar 17 01:10:08 CET 2008


There's been some progress, using the boost object implementation.
However it appears that the "chg" method of the DerivedO object is not
overridden properly.  So when it is changed in python, I get what I
expect, but when it is changed in C++, it appears to run the Base::chg
method instead of the DerivedO::chg method.  I'm sure I'm only missing
some tiny detail now.

---- mymodule.cpp ------------------------------------------------

#define MYTYPE object
#define MYDEFAULT object(0)

/*

#define MYTYPE string
#define MYDEFAULT ""

*/


#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#include <boost/python.hpp>
using namespace boost::python;

struct Base
{
  Base() { s = MYDEFAULT ; }
  Base(MYTYPE input){ s = input; }
  virtual ~Base() {}
  virtual MYTYPE run() { return s; }
  virtual void   chg(MYTYPE input) { s = input; }
private:
  MYTYPE s;
};

struct BaseWrap : Base, wrapper<Base>
{
  BaseWrap() : Base() {}
  BaseWrap(MYTYPE input) : Base(input) {}

  MYTYPE run() {
    if (override run = this->get_override("run"))
      return run();
    return Base::run();
  }

  MYTYPE default_run() {
    return this->Base::run();
  }

  void chg(MYTYPE input) {
    if (override chg = this->get_override("chg"))
      chg(input);
    Base::chg(input);
  }

  void default_chg(MYTYPE input) {
    this->Base::chg(input);
  }
};

typedef boost::shared_ptr<Base> BasePtr;

BasePtr g(new Base);

BasePtr get_g() {
  return g;
}

BasePtr set_g(BasePtr input_g) {
  BasePtr tmp;
  tmp = g;
  g = input_g;
  return tmp;
}

MYTYPE run_g() {
  MYTYPE tmp;
  tmp = g->run();
  return tmp;
}

void chg_g(MYTYPE input) {
  g->chg(input);
}

BOOST_PYTHON_MODULE(mymodule) {

  def("set_g", set_g);
  def("get_g", get_g);
  def("run_g", run_g);
  def("chg_g", chg_g);

  class_<BaseWrap, boost::noncopyable>("Base", init<>())
    .def(init<MYTYPE>())
    .def("run", &Base::run, &BaseWrap::default_run)
    .def("chg", &Base::chg, &BaseWrap::default_chg)
    ;

  register_ptr_to_python< BasePtr >();

}

---- test.py ------------------------------------------------

#!/usr/bin/env python

from mymodule import *

class DerivedS( Base ):
    def run( self ):
        x = Base.run( self )
        return x+x

class DerivedO( Base ):
    def chg( self, val ):
        y = [1,
             1.0,
             'string',
             ['array'],
             ('tuple',)
            ][val]
        Base.chg( self, y )
    def run( self ):
        x = Base.run( self )
        return x+x # defined for all 5 types above.

---- test run ------------------------------------------------

>>> from mymodule import *
>>> b1 = Base()
>>> b1.run()
0
>>> x = b1.run()
>>> set_g(b1)
<mymodule.Base object at 0x4020d3ac>
>>> run_g()
0
>>> b2 = Base('init_str')
>>> ib1 = set_g(b2)
>>> ib1.run()
0
>>> b2.run()
'init_str'
>>> run_g()
'init_str'
>>> chg_g(40)
>>> b2.run()
40
>>> run_g()
40
>>> ds = DerivedS('derived')
>>> ib2=set_g(ds)
>>> ib2.run()
40
>>> ds.run()
'derivedderived'
>>> run_g()
'derivedderived'
>>> ds.chg('changed in python ')
>>> ds.run()
'changed in python changed in python '
>>> chg_g('changed in C++ ')
>>> run_g()
'changed in C++ changed in C++ '
>>> ds.run()
'changed in C++ changed in C++ '
>>> class DerivedO( Base ):
...     def chg( self, val ):
...         y = [1,
...              1.0,
...              'string',
...              ['array'],
...              ('tuple',)
...             ][val]
...         Base.chg( self, y )
...     def run( self ):
...         x = Base.run( self )
...         return x+x # defined for all 5 types above.
...
>>> do = DerivedO()
>>> do.run()
0
>>> ids = set_g(do)
>>> ids.run()
'changed in C++ changed in C++ '
>>> do.chg(1)
>>> do.run()
2.0
>>> do.chg(2)
>>> do.run()
'stringstring'
>>> do.chg(3)
>>> do.run()
['array', 'array']
>>> run_g()
['array', 'array']
>>> do.chg(4)
>>> run_g()
('tuple', 'tuple')
>>> chg_g(2)
>>> do.run()
4
>>> chg_g(1)
>>> do.run()
2
>>> chg_g('this is ')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in chg
TypeError: list indices must be integers
>>> chg_g(3)
>>> run_g()
6
>>> do.chg(1)
>>> do.run()
2.0
>>> do.chg(2)
>>> do.run()
'stringstring'
>>> do.chg(3)
>>> do.run()
['array', 'array']
>>> do.chg(4)
>>> do.run()
('tuple', 'tuple')
>>> do.chg(0)
>>> do.run()
2
>>> run_g()
2
>>> chg_g(0)
>>> run_g()
0
>>> chg_g(1)
>>> run_g()
2
>>> chg_g(2)
>>> run_g()
4
>>> do.run()
4
>>> do.chg(2)
>>> do.run()
'stringstring'
>>> run_g()
'stringstring'
>>> chg_g(2)
>>> do.run()
4
>>> run_g()
4
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080316/a42122a3/attachment.htm>


More information about the Cplusplus-sig mailing list