From: Philipp K. <oe...@gm...> - 2009-05-26 10:17:09
|
Hi, SWIG ignores the conversion operators. But is there a way to fake the behaviour of a conversion operator? Thanks in advance, Philipp For illustration, some example code for my problem: >>> import conv_test as ct >>> b=ct.B() >>> ct.print_a(b) # Throws: TypeError: in method 'print_a', argument 1 of type 'test::A const &' with the following source files: conv_test.h #ifndef __conv_test_h #define __conv_test_h #include <iostream> namespace test { class A // Just a class { }; class B // Owns an A, and should be useable like an A { A* a; public: B() : a(new A) {} A& get_A() {return *a;} ~B() { delete a; std::cout << " B deleted" << std::endl;} // Conversion operators operator test::A&() {return *a;} operator const test::A&() const {return *a;} }; // Function expecting an A, should work with a B, too void print_a(const test::A& a) { std::cout << "A printed" << std::endl; } // Proof for the working conversion operator on the C++ side void print_b(const B& b) { print_a(b); } } #endif conv_test.i : %module conv_test %{ #include "conv_test.h" %} %include "conv_test.h" |
From: Miklos V. <vm...@fr...> - 2009-05-26 10:54:03
|
On Tue, May 26, 2009 at 12:17:01PM +0200, Philipp Kraft <oe...@gm...> wrote: > SWIG ignores the conversion operators. But is there a way to fake the > behaviour of a conversion operator? Did you try using %rename? You could rename operator& to getReference or something. |
From: Philipp K. <oe...@gm...> - 2009-05-26 12:02:35
|
>On Tue, May 26, 2009 at 12:17:01PM +0200, Philipp Kraft <oe...@gm...> wrote: >> SWIG ignores the conversion operators. But is there a way to fake the >> behaviour of a conversion operator? >Did you try using %rename? You could rename operator& to getReference or something. Thank you for the answer. Maybe I wasn't precise enough. It is not the problem to access A from B with some function (get_A is a member of B) but to use b as an A in a "quasi duck typing way". This works: >>> ct.print_a(b.get_A()) # but it's ugly and hard to explain to Non-C++ Python programmers This should work: >>> ct.print_a(b) # Simple to use, but how to do it with SWIG? The idea is to have a "HAS A" relationship, and, in some cases an "IS A" relationship-like behaviour without using inheritance. Thanks, Philipp |
From: Josh C. <jc...@nc...> - 2009-05-26 14:13:40
|
On Tue, 26 May 2009, Philipp Kraft wrote: > Maybe I wasn't precise enough. It is not the problem to access A from B with > some function (get_A is a member of B) but to use b as an A in a "quasi duck > typing way". > This works: >>>> ct.print_a(b.get_A()) # but it's ugly and hard to explain to Non-C++ > Python programmers > > This should work: >>>> ct.print_a(b) # Simple to use, but how to do it with SWIG? > > The idea is to have a "HAS A" relationship, and, in some cases an "IS A" > relationship-like behaviour without using inheritance. You could provide typemaps for A& that accept B. Alternatively, if the number of functions is small you could provide overloads that take a B& for wrapping purposes. Josh |
From: William S F. <ws...@fu...> - 2009-05-26 21:56:10
|
Josh Cherry wrote: > > On Tue, 26 May 2009, Philipp Kraft wrote: > >> Maybe I wasn't precise enough. It is not the problem to access A from B with >> some function (get_A is a member of B) but to use b as an A in a "quasi duck >> typing way". >> This works: >>>>> ct.print_a(b.get_A()) # but it's ugly and hard to explain to Non-C++ >> Python programmers >> >> This should work: >>>>> ct.print_a(b) # Simple to use, but how to do it with SWIG? >> The idea is to have a "HAS A" relationship, and, in some cases an "IS A" >> relationship-like behaviour without using inheritance. > > You could provide typemaps for A& that accept B. Alternatively, if the > number of functions is small you could provide overloads that take a B& > for wrapping purposes. > Also take a look at %implicitconv documented in the CHANGES file. If that doesn't work, can you add conversion operators dealing with pointers as well as references in your code? If so you should be able to use %types. Let me know and I'll try put together an example. William |
From: <oe...@gm...> - 2009-06-02 11:26:27
|
> Josh Cherry wrote: > > > > On Tue, 26 May 2009, Philipp Kraft wrote: > > > >> Maybe I wasn't precise enough. It is not the problem to access A from B > with > >> some function (get_A is a member of B) but to use b as an A in a "quasi > duck > >> typing way". > >> This works: > >>>>> ct.print_a(b.get_A()) # but it's ugly and hard to explain to Non-C++ > >> Python programmers > >> > >> This should work: > >>>>> ct.print_a(b) # Simple to use, but how to do it with SWIG? > >> The idea is to have a "HAS A" relationship, and, in some cases an "IS > A" > >> relationship-like behaviour without using inheritance. > > > > You could provide typemaps for A& that accept B. Alternatively, if the > > number of functions is small you could provide overloads that take a B& > > for wrapping purposes. > > > Also take a look at %implicitconv documented in the CHANGES file. If > that doesn't work, can you add conversion operators dealing with > pointers as well as references in your code? If so you should be able to > use %types. Let me know and I'll try put together an example. > > William Thank you for your answers! Last comment first: I do have access to the C++ code, putting in more operators is no problem. But, since there is no "simple" workaround, I'd tried to avoid the usage of the conversion operator and still hold the API simple. But I ran into a couple of new problems... First to say, in my real code A is a vector, therefore typemaps are not an alternative, since I don't want to fiddle around with std_vector.i like problems. The extended example source code for the problems I ran into is: **conv_test.h** ifndef __conv_test_h #define __conv_test_h #include <iostream> namespace test { class A { }; class C : public A { public: int Number; C(int n) : Number(n) {} }; class B { A* a; public: B() : a(new A) {} A& get_A() {return *a;} ~B() { delete a; std::cout << " B deleted" << std::endl;} #ifndef SWIG operator test::A&() {return *a;} operator const test::A&() const {return *a;} #endif }; void print_a(const test::A& a) { std::cout << "A printed" << std::endl; } void print_b(const B& b) { print_a(b); } } #endif **conv_test.i** %include "std_vector.i" %module conv_test %{ #include "conv_test.h" %} %implicitconv test::C; %include "conv_test.h" %template(c_vector) std::vector<test::C*>; The workaround idea was to expose the vector as an attribute. This is not working, because it seems like std_vector.i has problems with derived classes (see extended example for source). >>> import conv_test as ct >>> # c_vector is %template(c_vector) std::vector<test::C*>; >>> cv=ct.c_vector() >>> cv.append(ct.C(1)) # The A is the interesting part... >>> print cv[0] <conv_test.A; proxy of <Swig Object of type 'test::C *' at 0x00C2B180> > >>> cv[0].Number AttributeError Is this a SWIG-Bug? Using implicitconv: I'm not sure how implicitconv should deal with this fake "IS A" problem. But it seems there is more to %implicitconv since from the description in the changes file I would expect this to work: >>> cv.append(1) ->TypeError I'm using SWIG 1.3.38 and MinGW on Windows. Thank you, Philipp -- GMX FreeDSL Komplettanschluss mit DSL 6.000 Flatrate und Telefonanschluss nur 17,95 Euro/mtl.!* http://portal.gmx.net/de/go/dsl02 |
From: William S F. <ws...@fu...> - 2013-08-28 19:58:01
|
On 02/06/09 12:26, oe...@gm... wrote: > >> Josh Cherry wrote: >>> >>> On Tue, 26 May 2009, Philipp Kraft wrote: >>> >>>> Maybe I wasn't precise enough. It is not the problem to access A from B >> with >>>> some function (get_A is a member of B) but to use b as an A in a "quasi >> duck >>>> typing way". >>>> This works: >>>>>>> ct.print_a(b.get_A()) # but it's ugly and hard to explain to Non-C++ >>>> Python programmers >>>> >>>> This should work: >>>>>>> ct.print_a(b) # Simple to use, but how to do it with SWIG? >>>> The idea is to have a "HAS A" relationship, and, in some cases an "IS >> A" >>>> relationship-like behaviour without using inheritance. >>> >>> You could provide typemaps for A& that accept B. Alternatively, if the >>> number of functions is small you could provide overloads that take a B& >>> for wrapping purposes. >>> >> Also take a look at %implicitconv documented in the CHANGES file. If >> that doesn't work, can you add conversion operators dealing with >> pointers as well as references in your code? If so you should be able to >> use %types. Let me know and I'll try put together an example. >> >> William > > Thank you for your answers! > > Last comment first: > I do have access to the C++ code, putting in more operators is no problem. > > But, since there is no "simple" workaround, I'd tried to avoid the usage of the conversion operator and still hold the API simple. But I ran into a couple of new problems... > > First to say, in my real code A is a vector, therefore typemaps are not an alternative, since I don't want to fiddle around with std_vector.i like problems. > > The extended example source code for the problems I ran into is: > > **conv_test.h** > > ifndef __conv_test_h > #define __conv_test_h > #include <iostream> > namespace test { > class A > { }; > class C : public A > { > public: > int Number; > C(int n) : Number(n) {} > }; > > class B > { > A* a; > public: > B() : a(new A) {} > A& get_A() {return *a;} > ~B() { delete a; std::cout << " B deleted" << std::endl;} > #ifndef SWIG > operator test::A&() {return *a;} > operator const test::A&() const {return *a;} > #endif > }; > void print_a(const test::A& a) > { > std::cout << "A printed" << std::endl; > } > void print_b(const B& b) > { > print_a(b); > } > > } > #endif > > > **conv_test.i** > > %include "std_vector.i" > %module conv_test > %{ > #include "conv_test.h" > %} > > %implicitconv test::C; > %include "conv_test.h" > > > %template(c_vector) std::vector<test::C*>; > > > The workaround idea was to expose the vector as an attribute. This is not working, because it seems like std_vector.i has problems with derived classes (see extended example for source). > >>>> import conv_test as ct >>>> # c_vector is %template(c_vector) std::vector<test::C*>; >>>> cv=ct.c_vector() >>>> cv.append(ct.C(1)) > # The A is the interesting part... >>>> print cv[0] > <conv_test.A; proxy of <Swig Object of type 'test::C *' at 0x00C2B180> > >>>> cv[0].Number > AttributeError > This is probably a memory error - the vector containing a pointer to an instance of test::C that no longer exists. > > Is this a SWIG-Bug? > > Using implicitconv: I'm not sure how implicitconv should deal with this fake "IS A" problem. But it seems there is more to %implicitconv since from the description in the changes file I would expect this to work: > >>>> cv.append(1) > ->TypeError > The problem here is you cannot implicitly convert to a pointer (the type of vector elements). The element needs to be a reference or held by value. William |