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

Josh Stratton strattonbrazil at gmail.com
Tue Aug 30 16:45:21 CEST 2011


Oh, okay.  So I can create a module...

#include "scene.h"
BOOST_PYTHON_MODULE(scene)
{
    class_<Scene>("Scene");
}

and then import it (even though) in my python I normally don't import
things I'm not creating.  I'm assuming this is a boost-python thing to
get the class into scope, which gets rid of the "converter found for
C++ type: Scene" error.

from scene import Scene # in my python code

In my terminal I get...

Error in Python: <class 'Boost.Python.ArgumentError'>: Python argument types in
    Mesh.buildByIndex(Scene, PrimitiveParts)
did not match C++ signature:
    buildByIndex(QSharedPointer<Scene>, PrimitiveParts):   File
"<string>", line 21, in processFile

for this function:

    static void                  buildByIndex(SceneP scene,
PrimitiveParts parts);

The function I'm calling has SceneP typedeffed as a
QSharedPointer<Scene> and I'm assuming this error is because I haven't
made a Scene to QSharedPointer<Scene> converter, which should just
wrap the Scene object when it comes in requiring a custom conversion
function.

struct QSceneFromPythonScene
{
    static PyObject* convert(Scene const& s)
    {
        return boost::python::incref(boost::python::object(SceneP(&s)));
    }
};

But I'm not converting that properly, I guess.

"invalid conversion of const Scene* to Scene*.

On Mon, Aug 29, 2011 at 11:08 AM, Jim Bosch <talljimbo at gmail.com> wrote:
> 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