Hi, I am wrapping a library, and everything is going well. But now I am trying to wrap some virtual methods. After that a strange behavior is happening (I am using boost 1.32). I am using Pyste to wrap a "scratch code" for me, and I then manually insert some wrapped functions/classes/enums to the definitive source. (This approach might be strange, but it is good for me. It helps me learning Boost.Pythonconstructs, and it's a way to control errors for each step.) The error consist basically of a wrapped virtual method of the "QObject" class being called *without* it being reimplemented in Python. Of course it was reimplemented in C++, when the "QObject_Wrapper" class was created. Pyste is generating the "QObject_Wrapper" with the overloaded constructors, a "PyObject* py_self" reference to the Python object, everything explicit! On the other hand, I saw on the tutorial that you should use a construct like: struct BaseWrap : Base, wrapper<Base> { int f() { if (override f = this->get_override("f")) return f(); // note* return Base::f(); } int default_f() { return this->Base::f(); } }; // *note: on MSVC use // return call<char const*>(f.ptr()); I think that this will solve the problem, because it tests if there is a overriden method. I am still confused if wrapper<...> will create the apropriate contructors. So what do "wrapper<..>" really do? Another thing that I noticed is that I have to reimplement virtual methods on every derived class. This is an accumulative task. Am I right? So, what is the right and safe way to wrap virtual methods? Thanks, [Eric Jardim]
Eric Jardim <ericjardim@gmail.com> writes:
I saw on the tutorial that you should use a construct like:
struct BaseWrap : Base, wrapper<Base> { int f() { if (override f = this->get_override("f")) return f(); // note* return Base::f(); }
int default_f() { return this->Base::f(); }
Does the tutorial really recommend that default_f? I can't imagine why. That's just wrong; you don't need it and it's a bad idea to use it. [Joel, can you please fix this ASAP, and the use of default_f further down?]
};
// *note: on MSVC use // return call<char const*>(f.ptr());
I think that this will solve the problem, because it tests if there is a overriden method. I am still confused if wrapper<...> will create the apropriate contructors.
wrappeer<...> doesn't create any constructors by itself.
So what do "wrapper<..>" really do?
Exactly what's described in http://www.boost.org/libs/python/doc/v2/wrapper.html#wrapper-spec
Another thing that I noticed is that I have to reimplement virtual methods on every derived class. This is an accumulative task. Am I right?
I don't know what you mean.
So, what is the right and safe way to wrap virtual methods?
Everything the tutorial says, aside from the definition and use of default_f, seems to be right. -- Dave Abrahams Boost Consulting www.boost-consulting.com
2005/8/5, David Abrahams <dave@boost-consulting.com>:
Does the tutorial really recommend that default_f? I can't imagine why. That's just wrong; you don't need it and it's a bad idea to use it. [Joel, can you please fix this ASAP, and the use of default_f further down?]
Beside the tutorial, Pyste itself generate "default_..." methods.
Another thing that I noticed is that I have to reimplement virtual methods
on every derived class. This is an accumulative task. Am I right?
I don't know what you mean.
Suppose you have class A, B and C. C is derived from B, and B derived from A (A <- B <- C). Suppose you have a virtual method "f" (pure or not) defined on the A class scope. Suppose that you want to expose this method, so user can, in Python, extend some class (A, B or C) If you want to extend class A, in Python, that's Ok. When you create a new A class in Python, you are actually creating a A_Wrapper object. But if you want to extend B or C, they don't know about the A_Wrapper. So, you must create B_Wrapper, C_Wrapper and re-expose "f" on both. Hope to make it clear now. Is this right, or not. Everything the tutorial says, aside from the definition and use of
default_f, seems to be right.
It looks like the docs use the "default_..." functions too: http://www.boost.org/libs/python/doc/v2/wrapper.html I still don't understand: should I use the "defaul_..." function (in a different way) or not use it? Let's see a real (correct) example, please. Thanks, [Eric Jardim]
Eric Jardim <ericjardim@gmail.com> writes:
2005/8/5, David Abrahams <dave@boost-consulting.com>:
Does the tutorial really recommend that default_f? I can't imagine why. That's just wrong; you don't need it and it's a bad idea to use it. [Joel, can you please fix this ASAP, and the use of default_f further down?]
My mistake; I was just mis-remembering. Please see: http://mail.python.org/pipermail/c++-sig/2004-July/007844.html [And my apologies to Joel]
Beside the tutorial, Pyste itself generate "default_..." methods.
That is correct.
Another thing that I noticed is that I have to reimplement virtual methods
on every derived class. This is an accumulative task. Am I right?
I don't know what you mean.
Suppose you have class A, B and C. C is derived from B, and B derived from A (A <- B <- C). Suppose you have a virtual method "f" (pure or not) defined on the A class scope. Suppose that you want to expose this method, so user can, in Python, extend some class (A, B or C)
If you want to extend class A, in Python, that's Ok. When you create a new A p class in Python, you are actually creating a A_Wrapper object. But if you want to extend B or C, they don't know about the A_Wrapper. So, you must create B_Wrapper, C_Wrapper and re-expose "f" on both.
Hope to make it clear now. Is this right, or not.
If you want to derive from B or C in Python and override "f" such that when C++ calls it, the Python implementation is invoked, that's correct.
I still don't understand: should I use the "defaul_..." function (in a different way) or not use it?
Use it.
Let's see a real (correct) example, please.
You can always know that the examples in libs/python/test are correct. See libs/python/test/polymorphism2.cpp/.py -- Dave Abrahams Boost Consulting www.boost-consulting.com
2005/8/5, David Abrahams <dave@boost-consulting.com>:
So, what is the right and safe way to wrap virtual methods?
Everything the tutorial says, aside from the definition and use of
default_f, seems to be right.
I have more doubts. 1 - using the wrapper<...> approach, the tutorial suggests me that I should expose my class like this: class_<BaseWrap, boost::noncopyable>("Base") .def("f", &Base::f, &BaseWrap::default_f) ; But what if some "Base" object where create, not by the Python code. As I exposed "BaseWrap", "Base" was not actually exposed. Will it be a problem? 2 - How do I expose the constructors of the "Base" class on the "BaseWrap" class? Should I define it again? Should I define the PyObject* as the first parameter, or treat it as a normal class? The solution I think will work: I think that I will have to create 2 kind of objects. The normal "QObject" wrapper, whithout the virtual functions overriden, and a "QCustomObject", class that will never be created by C++ classes. If the user wants to reimplement any virtual function, he should use this class. If what I say is wrong, or a bad idea, just tell me. [Eric Jardim]
participants (2)
-
David Abrahams -
Eric Jardim