Hi all,<br><br>I&#39;m new to boost::python, and I need to write a program that defines<br>an abstract base class in C++, and a derived class in Python.&nbsp; Then I<br>want to instantiate the derived class in python and store its address<br>
in a C++ variable of type pointer to the base type and call python<br>methods in the derived type polymorphically from C++.&nbsp; All of that<br>works.&nbsp; The remaining problem is how to let the python function return<br>arbitrary python objects to C++, and have C++ hold a pointer to the<br>
arbitrary returned result.&nbsp; Below is my code so far, it isn&#39;t working<br>as written (but when I change all the &#39;PyObject *&#39; to C++ type string and make<br>other appropriate changes in the python file, it works for returning<br>
string types.&nbsp; Can anyone give me an idea what changes are required in<br>the code to do what I need ?<br><br>Thanks,<br><br>Ambrose<br><br>The two files are included below:<br><br>mymodule.cpp ----------------------------------------------------------------------------------------<br>
<br>#include &lt;iostream&gt;<br>#include &lt;fstream&gt;<br>#include &lt;string&gt;<br>using namespace std;<br><br>#include &lt;boost/python.hpp&gt;<br>using namespace boost::python;<br><br>struct Base <br>{<br>&nbsp; Base() { s = Py_None; }<br>
&nbsp; Base(PyObject *input){ s = input; }<br>&nbsp; virtual ~Base() {}<br>&nbsp; virtual PyObject *run() { return s; }<br>private:<br>&nbsp; PyObject *s;<br>};<br><br>struct BaseWrap : Base, wrapper&lt;Base&gt;<br>{<br>&nbsp; BaseWrap() : Base() {}<br>
&nbsp; BaseWrap(PyObject *input) : Base(input) {}<br><br>&nbsp; PyObject *run() {<br>&nbsp;&nbsp;&nbsp; if (override run = this-&gt;get_override(&quot;run&quot;))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return run();<br>&nbsp;&nbsp;&nbsp; return Base::run();<br>&nbsp; }<br><br>&nbsp; PyObject *default_run() {<br>
&nbsp;&nbsp;&nbsp; return this-&gt;Base::run();<br>&nbsp; }<br>};<br><br>typedef boost::shared_ptr&lt;Base&gt; BasePtr;<br><br>BasePtr g(new Base);<br><br>BasePtr get_g() {<br>&nbsp; return g;<br>}<br><br>BasePtr set_g(BasePtr input_g) {<br>&nbsp; BasePtr tmp;<br>
&nbsp; tmp = g;<br>&nbsp; g = input_g;<br>&nbsp; return tmp;<br>}<br><br>PyObject *run_g() {<br>&nbsp; PyObject *tmp;<br>&nbsp; tmp = g-&gt;run();<br>&nbsp; return tmp;<br>}<br><br>BOOST_PYTHON_MODULE(mymodule) {<br>&nbsp; <br>&nbsp; def(&quot;set_g&quot;, set_g);<br>
&nbsp; def(&quot;get_g&quot;, get_g);<br>&nbsp; def(&quot;run_g&quot;, run_g);<br><br>&nbsp; class_&lt;BaseWrap, boost::noncopyable&gt;(&quot;Base&quot;, init&lt;&gt;()) <br>&nbsp;&nbsp;&nbsp; .def(init&lt;PyObject *&gt;())<br>&nbsp;&nbsp;&nbsp; .def(&quot;run&quot;, &amp;Base::run, &amp;BaseWrap::default_run)<br>
&nbsp;&nbsp;&nbsp; ;<br><br>&nbsp; register_ptr_to_python&lt; BasePtr &gt;();<br><br>}<br><br>----- test.py ----------------------------------------------------------------------------------------------------<br>#!/usr/bin/env python<br><br>
from mymodule import *<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>class DerivedS( Base ):<br>&nbsp;&nbsp;&nbsp; def run( self ):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = Base.run( self )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x+x<br><br>class DerivedM( Base ):<br><br>&nbsp;&nbsp;&nbsp; def __init__( self ):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; import random<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = random.randint(0,4)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if x == 0:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.x = 1 # int<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif x == 1:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.x = 1.0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif x == 2:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.x = &#39;string&#39;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif x == 3:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.x = [&#39;array&#39;]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif x == 4:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.x = (&#39;tuple&#39;)<br><br>&nbsp;&nbsp;&nbsp; def run( self ):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.x + self.x # defined for all 5 types above<br><br># minimal set of tests:<br>
<br>b1 = Base()<br>set_g(b1)<br>x = b1.run()&nbsp; # test from python should print nothing<br>y = run_g()&nbsp;&nbsp; # test call from C++ should print nothing<br>if x is None: print &#39;x is None&#39;<br>if y is None: print &#39;y is None&#39;<br>
<br>b2 = Base(&#39;init_str&#39;)<br>ib1 = set_g(b2) # want something identical to b1<br>b2.run()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # want &#39;init_str&#39;<br>run_g()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # want &#39;init_str&#39;<br><br>ds = DerivedS(&#39;derived&#39;)<br>ib2 = set_g(ds) # want something identical to b2<br>
ds.run()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # want &#39;derivedderived&#39;<br>run_g()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # want &#39;derivedderived&#39;<br><br>dm = DerivedM()<br>ids = set_g(dm) # want something identical to ds<br>dm.run()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # want one of the values<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 2, 2.0, &#39;stringstring&#39;, [&#39;array&#39;,&#39;array&#39;], (&#39;tuple&#39;,&#39;tuple&#39;)<br>run_g()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # same output as previous<br><br><br>