[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