[C++-sig] sending a c++ class to a python function

Jim Bosch talljimbo at gmail.com
Mon Aug 29 20:08:23 CEST 2011


Normally a to-python converter is needed when you have a function that 
returns a C++ object, and you want to wrap that function so the returned 
thing can be used in Python.  I don't see any functions that return a 
Scene object.  They will also enable expressions of the form 
"object(scene)", but you can't use that sort of expression to define the 
converter itself.

When you're writing the conversion function, remember that Boost.Python 
really doesn't know anything about your class unless you tell it about 
it using a boost::python::class_ definition, and doing that will already 
define a to-python converter for it.  The instructions you're following 
are for things like strings that already have a Python type they can be 
converted to; you probably want to use class_ for something like Scene. 
  Now, if you just wanted to convert Scene to a dict instead of having a 
Scene type in Python, a custom conversion would indeed be the way to go, 
but you'd need to create a dict and fill it in the convert function.

Anyhow, my best guess for the segfault is that you have an infinite 
recursion - when you call object(scene), it needs to look for a 
to-python converter in the registry.  So it finds yours, which calls 
object(scene).  Repeat.

Jim




On 08/28/2011 08:22 PM, Josh Stratton wrote:
> I'm getting an error when I try to pass down my object that results in
> a seg fault.  I've registered my class I'm sending down, but when I
> actually send it, my program exits at this line in the library right
> after I call the importFile() function...
>
>          return call<obj>(get_managed_object(self, tag),
> BOOST_PP_ENUM_PARAMS_Z(1, N, a));
>
> // here's the class I'm trying to send down
> class Scene
> {
> public:
>      MeshP                       mesh(int key);
>      void                        clearScene();
>      CameraP                     createCamera(QString name);
>      MeshP                       createMesh(QString name);
>      void                        setMesh(int meshKey, MeshP mesh) {
> _meshes[meshKey] = mesh; }
>      QHashIterator<int, MeshP>    meshes() { return
> QHashIterator<int,MeshP>(_meshes); }
>      QHashIterator<int, CameraP>  cameras() { return
> QHashIterator<int,CameraP>(_cameras); }
>      CameraP                     fetchCamera(QString name);
>      QList<QString>               importExtensions();
>      void                        importFile(QString fileName);
>      void                        evalPythonFile(QString fileName);
>                                  Scene();
> protected:
>      int                                uniqueCameraKey();
>      int                                uniqueMeshKey();
>      QString                            uniqueName(QString prefix);
>
> private:
>      QHash<int,MeshP>                    _meshes;
>      QHash<int,CameraP>                  _cameras;
>      //QHash<int,Light*>       _lights;
>      QSet<QString>                       _names;
> //    PythonQtObjectPtr                  _context;
>      object                             _pyMainModule;
>      object                             _pyMainNamespace;
> public slots:
>      void                               pythonStdOut(const QString&s)
> { std::cout<<  s.toStdString()<<  std::flush; }
>      void                               pythonStdErr(const QString&s)
> { std::cout<<  s.toStdString()<<  std::flush; }
> };
>
> // first I create the mapping, which I'm not sure is correct, trying
> to follow: http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/
> struct SceneToPython
> {
>      static PyObject* convert(Scene const&  scene)
>      {
>          return boost::python::incref(boost::python::object(scene).ptr());
>      }
> };
>
> // then I register it
>      boost::python::to_python_converter<Scene,SceneToPython>();
>
> // then I send it down from inside my Scene object
>      try {
>          object processFileFunc =
> _pyMainModule.attr("MeshImporter").attr("processFile");
>          processFileFunc(this, fileName); // seems to error here
>      } catch (boost::python::error_already_set const&) {
>          QString perror = parse_python_exception();
>          std::cerr<<  "Error in Python: "<<  perror.toStdString()<<  std::endl;
>      }
>
> I'm not really sure what actually is wrong besides something being
> setup incorrectly.  Do I need to make a python-to-C++ converter as
> well even if I'm not sending it back to C++?  Or is my convert()
> function just improperly implemented?  I wasn't sure how much I need
> to actually get it to map correctly.  Thanks.
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig



More information about the Cplusplus-sig mailing list