Re : Re : Re : [boost] Re : Using an element of a class A in a constructor of a class B (reflection with boost::python)
Thank you for your answer, As I said, the solution I am currently using is working fine, I am just using a method explained in the tutorial for a function independant from any class: http://wiki.python.org/moin/boost.python/ExportingClasses and I extend it to a function of another class. You recommend to write things that way: class_< A_i, bp::bases<B> >(...); but, A_i are not derived from B, and as they are already derived from A_Base_j classes (some from a same base class, not all of them), I already declared their base classes. Declaring a function B::f(A& a, ...) in A as: .def("f", &B::f) keep C++ declaration (I mean, even if B::f is declared in A, it's declared as a method of B, which is correct). But what your are proposing seems not correct to me, as long as A isn't a derived class from B. Christophe Jean-Joseph ________________________________ De : Jim Bosch <talljimbo@gmail.com> À : christophe jean-joseph <jjchristophe@yahoo.fr> Envoyé le : Mercredi 21 mars 2012 4h35 Objet : Re: Re : [C++-sig] Re : [boost] Re : Using an element of a class A in a constructor of a class B (reflection with boost::python) On 03/20/2012 07:07 AM, christophe jean-joseph wrote:
Thank you for your answer and sorry for the delay: I finally used another solution. I used a setParam function instead of the constructor for boost::python. From the point of view of c++, the only difference is that the former constructor is now just calling setParam. This former constructor is ignored by boost::python, and instead setParam is reflected as a normal function. This works fine (my Python main produce, with less than 0.01% difference, the same results as the C++ main). But I am not satisfied with my solution for the following reason: if A and B are 2 classes, in order to reflect a function B::f(A& a, ....), I am writing things as follow as follow: Class_ <A>(usual declarations here) .def("f", &B::f) Class_ <B>(usual declarations here) .def("f", &B::f)
Which means, for n classes A_i (i from 1 to n) and a function of a class B b::f(A_1& a1, A_2& a2,...., A_n& an, ....) I'll have to write: Class_ <A_1>(usual declarations here) .def("f", &B::f) . . . Class_ <A_n>(usual declarations here) .def("f", &B::f) Class_ <B>(usual declarations here) .def("f", &B::f)
Which is not very clean, even though it's working. So if there is any other way to do that, I will be glad to hear it.
I'm a little confused; if the A classes do not inherit from B, why would you want to wrap a member function of B as a method of A? I don't think they would actually work, unless you've made sure all the A classes are convertible to B by some other mechanism. And if the A classes do inherit from B, if you use: class_< A_i, bp::bases<B> >(...); with no .def("f", ...), you'll still be able to use the "f" method in Python because it will be inherited from B. Jim
------------------------------------------------------------------------ *De :* Jim Bosch <talljimbo@gmail.com> *À :* christophe jean-joseph <jjchristophe@yahoo.fr>; Development of Python/C++ integration <cplusplus-sig@python.org> *Envoyé le :* Dimanche 18 mars 2012 0h22 *Objet :* Re: [C++-sig] Re : [boost] Re : Using an element of a class A in a constructor of a class B (reflection with boost::python)
On 03/15/2012 09:22 AM, christophe jean-joseph wrote: > Hello > > The situation is as follow. > I have a C++ code that I haven't written and that I barely can modified. > I am supposed to reflect this code in Python with boost. > In the code, I have something looking like this: > > Class A_Base { > A_Base(){}; > ~A_Base(){}; > Whatever virtual and pure virtual functions; > } > > Class A_Derived{ > A_Derived(Type1 arg1,...){whatever instructions;} > ~A_Derived(){}; > Whatever functions; > } > > Class B { > B(A_Base& aBase, double& x){}; > ~B(){}; > Whatever functions; > } > > In the C++ main, at some point aDerived A_Derived is set, and then > B(aDerived, x). > I need to reflect that under python. > Until now, I have been able, with a simple example, to reflect a > function f, which is not a ctor, from a class B using A_Base& as > argument type, but I can't figure out how to deal with it for a constructor. > Based on: > > http://wiki.python.org/moin/boost.python/ExportingClasses > > I am declaring f under both its class B and A_Base as follow: > > class_A_Base <A, boost::noncopyable>("A_Base", no_init) //this line can > be modified > .def("f", &B::f); > class_B <B, boost::noncopyable>("B", init< >()) //this line can be modified > .def("f", &B::f); > > > But when I try this for a constructor as f, it refuse to compile.
You don't wrap constructors the same way as functions (I don't think you can even take their address in C++). Instead, you use:
.def(init<T1,T2,...>())
(where T1,T2,... are the argument types of the constructor), or do the same thing in the init argument to class_ itself (as I've done below).
I think what you want is something like this (assuming A_Derived does actually inherit from A_Base, even though it doesn't in your example code):
class_<A_Base,noncopyable>("A_Base", no_init); class_<A_Derived,bases<A_Base>,noncopyable>("A_Derived", no_init); class_<B,noncopyable>("B", init<A,double>());
Note that the float you pass in as "x" to B's constructor will not be modified in Python; that's unavoidable in this case.
If that doesn't work, please post exactly what you're trying to compile; the example you posted has a few things that obviously won't compile, so it's hard to know exactly what the problem is.
Good luck!
Jim
On 03/21/2012 12:09 PM, christophe jean-joseph wrote:
Thank you for your answer,
As I said, the solution I am currently using is working fine, I am just using a method explained in the tutorial for a function independant from any class:
http://wiki.python.org/moin/boost.python/ExportingClasses
and I extend it to a function of another class. You recommend to write things that way:
class_< A_i, bp::bases<B> >(...);
but, A_i are not derived from B, and as they are already derived from A_Base_j classes (some from a same base class, not all of them), I already declared their base classes. Declaring a function B::f(A& a, ...) in A as: .def("f",&B::f) keep C++ declaration (I mean, even if B::f is declared in A, it's declared as a method of B, which is correct). But what your are proposing seems not correct to me, as long as A isn't a derived class from B.
Oh, I understand now. "B::f" is a static member function that takes an "A" as its first argument. You just want a more elegant way to wrap a lot of similar classes. You may not be able to get it a lot cleaner, but you can cut down some of the boilerplate by writing a templated function to wrap an "A" class. You can then just call that repeatedly: template <typename T> void wrapA(char const * name) { bp::class_<T>(name, ...) .def("F", &B::f) ; } BOOST_PYTHON_MODULE(whatever) { wrapA<A_1>("A_1"); wrapA<A_2>("A_2"); ... wrapA<A_n>("A_n"); } Of course, you'll have to modify it to do more than that, but hopefully that will get you started. Jim
Thank you very much for your suggestion. Jean-Joseph ________________________________ De : Jim Bosch <talljimbo@gmail.com> À : christophe jean-joseph <jjchristophe@yahoo.fr> Cc : "cplusplus-sig@python.org" <cplusplus-sig@python.org> Envoyé le : Mercredi 21 mars 2012 17h32 Objet : Re: Re : Re : [C++-sig] Re : [boost] Re : Using an element of a class A in a constructor of a class B (reflection with boost::python) On 03/21/2012 12:09 PM, christophe jean-joseph wrote:
Thank you for your answer,
As I said, the solution I am currently using is working fine, I am just using a method explained in the tutorial for a function independant from any class:
http://wiki.python.org/moin/boost.python/ExportingClasses
and I extend it to a function of another class. You recommend to write things that way:
class_< A_i, bp::bases<B> >(...);
but, A_i are not derived from B, and as they are already derived from A_Base_j classes (some from a same base class, not all of them), I already declared their base classes. Declaring a function B::f(A& a, ...) in A as: .def("f",&B::f) keep C++ declaration (I mean, even if B::f is declared in A, it's declared as a method of B, which is correct). But what your are proposing seems not correct to me, as long as A isn't a derived class from B.
Oh, I understand now. "B::f" is a static member function that takes an "A" as its first argument. You just want a more elegant way to wrap a lot of similar classes. You may not be able to get it a lot cleaner, but you can cut down some of the boilerplate by writing a templated function to wrap an "A" class. You can then just call that repeatedly: template <typename T> void wrapA(char const * name) { bp::class_<T>(name, ...) .def("F", &B::f) ; } BOOST_PYTHON_MODULE(whatever) { wrapA<A_1>("A_1"); wrapA<A_2>("A_2"); ... wrapA<A_n>("A_n"); } Of course, you'll have to modify it to do more than that, but hopefully that will get you started. Jim
participants (2)
-
christophe jean-joseph -
Jim Bosch