From: Ben W. <be...@sa...> - 2009-04-13 22:02:29
|
I want to do the following, but it doesn't work: %template(Foo) Foo<float>; SWIG (1.3.36, run as 'swig -python -c++ test.i') complains: Identifier 'Foo' redefined (ignored) (Renamed from 'Foo< float >'), The background: test.h looks like: template<typename T> class Foo {}; and test.i: %module test %{ #include "test.h" %} %include "test.h" %template(Foo) Foo<float>; i.e. C++ defines a template class 'Foo'. In reality, we always use a Foo<float> in the C++ code, so would like 'Foo' in the Python code to simply map to Foo<float> in C++. Is there any way to achieve this in SWIG? I tried the following instead: %rename(FooTemplate) Foo; %template(Foo) FooTemplate<float>; but that gives the following error: test.i:9: Error: Template 'FooTemplate' undefined. i.e. I guess template classes cannot be renamed. I guess I could work around this with something like %template(_InternalFoo) Foo<float>; and then add Foo = _InternalFoo to the generated test.py file, but this seems less than optimal. I would also prefer to avoid modifying the header file (or duplicating it into the .i file) since the real header is rather large. Ben -- be...@sa... http://salilab.org/~ben/ "It is a capital mistake to theorize before one has data." - Sir Arthur Conan Doyle |
From: William S F. <ws...@fu...> - 2009-04-15 23:22:44
|
Ben Webb wrote: > I want to do the following, but it doesn't work: > %template(Foo) Foo<float>; > > SWIG (1.3.36, run as 'swig -python -c++ test.i') complains: > Identifier 'Foo' redefined (ignored) (Renamed from 'Foo< float >'), > > The background: test.h looks like: > template<typename T> > class Foo {}; > > and test.i: > %module test > %{ > #include "test.h" > %} > %include "test.h" > %template(Foo) Foo<float>; > > i.e. C++ defines a template class 'Foo'. In reality, we always use a > Foo<float> in the C++ code, so would like 'Foo' in the Python code to > simply map to Foo<float> in C++. Is there any way to achieve this in > SWIG? I tried the following instead: > > %rename(FooTemplate) Foo; > %template(Foo) FooTemplate<float>; > > but that gives the following error: > test.i:9: Error: Template 'FooTemplate' undefined. > i.e. I guess template classes cannot be renamed. > > I guess I could work around this with something like > %template(_InternalFoo) Foo<float>; > > and then add > Foo = _InternalFoo > to the generated test.py file, but this seems less than optimal. I would > also prefer to avoid modifying the header file (or duplicating it into > the .i file) since the real header is rather large. > > Ben Hopefully the name conflict makes sense to you as Foo is already defined. You can fix this easily enough by %renaming the Foo to something else, then you can use the 'Foo' name again. Example below. William %rename(Foo_) Foo; %inline %{ template<typename T> class Foo {}; %} %template(Foo) Foo<float>; %inline %{ void method(Foo<float> ff) {} %} |
From: Ben W. <be...@sa...> - 2009-04-16 19:41:28
|
William S Fulton wrote: > Ben Webb wrote: >> I want to do the following, but it doesn't work: >> %template(Foo) Foo<float>; >> >> SWIG (1.3.36, run as 'swig -python -c++ test.i') complains: >> Identifier 'Foo' redefined (ignored) (Renamed from 'Foo< float >'), > Hopefully the name conflict makes sense to you as Foo is already > defined. I don't understand what you mean here - defined to Python? It's a template class - how can it be defined in Python? I thought only classes instantiated with %template were "defined" as far as Python is concerned? > You can fix this easily enough by %renaming the Foo to > something else, then you can use the 'Foo' name again. Example below. > %rename(Foo_) Foo; > %inline %{ > template<typename T> class Foo {}; > %} > > %template(Foo) Foo<float>; > > %inline %{ > void method(Foo<float> ff) {} > %} Thanks, but that doesn't seem to work (with SWIG 1.3.36). When I build that with swig -c++ -python -module test test.i g++ -Wall -I/usr/include/python2.5 -fPIC -shared -o _test.so test1_wrap.cxx and then run import test print test.Foo print test.Foo() I get the following output: <class 'test.Foo'> Traceback (most recent call last): File "run.py", line 3, in <module> print test.Foo() File "test.py", line 56, in __init__ def __init__(self, *args, **kwargs): raise AttributeError, "No constructor defined" AttributeError: No constructor defined Whereas, if I use my hacked interface: %inline %{ template<typename T> class Foo {}; %} %template(Foo_) Foo<float>; %inline %{ void method(Foo<float> ff) {} %} %pythoncode { Foo = Foo_ } I get the following: <class 'test.Foo_'> <test.Foo_; proxy of <Swig Object of type 'Foo< float > *' at 0x13e0420> > which is the desired behavior (other than it calling the class Foo_, which I can live with). Any ideas why this happens? Ben -- be...@sa... http://salilab.org/~ben/ "It is a capital mistake to theorize before one has data." - Sir Arthur Conan Doyle |
From: William S F. <ws...@fu...> - 2009-04-20 18:32:01
|
Ben Webb wrote: > William S Fulton wrote: >> Ben Webb wrote: >>> I want to do the following, but it doesn't work: >>> %template(Foo) Foo<float>; >>> >>> SWIG (1.3.36, run as 'swig -python -c++ test.i') complains: >>> Identifier 'Foo' redefined (ignored) (Renamed from 'Foo< float >'), >> Hopefully the name conflict makes sense to you as Foo is already >> defined. > > I don't understand what you mean here - defined to Python? It's a > template class - how can it be defined in Python? I thought only classes > instantiated with %template were "defined" as far as Python is concerned? > >> You can fix this easily enough by %renaming the Foo to >> something else, then you can use the 'Foo' name again. Example below. >> %rename(Foo_) Foo; >> %inline %{ >> template<typename T> class Foo {}; >> %} >> >> %template(Foo) Foo<float>; >> >> %inline %{ >> void method(Foo<float> ff) {} >> %} > > Thanks, but that doesn't seem to work (with SWIG 1.3.36). When I build > that with > swig -c++ -python -module test test.i > g++ -Wall -I/usr/include/python2.5 -fPIC -shared -o _test.so test1_wrap.cxx > > and then run > import test > print test.Foo > print test.Foo() > > > I get the following output: > <class 'test.Foo'> > Traceback (most recent call last): > File "run.py", line 3, in <module> > print test.Foo() > File "test.py", line 56, in __init__ > def __init__(self, *args, **kwargs): raise AttributeError, "No > constructor defined" > AttributeError: No constructor defined > > Whereas, if I use my hacked interface: > %inline %{ > template<typename T> class Foo {}; > %} > > %template(Foo_) Foo<float>; > > %inline %{ > void method(Foo<float> ff) {} > %} > > %pythoncode { > Foo = Foo_ > } > > I get the following: > <class 'test.Foo_'> > <test.Foo_; proxy of <Swig Object of type 'Foo< float > *' at 0x13e0420> > > > which is the desired behavior (other than it calling the class Foo_, > which I can live with). Any ideas why this happens? > Sorry, I used the Java module and there everything works as expected. The '%rename(Foo_) Foo' is a global rename, so it renames both the class and the constructors. Then there is a quirk in the Python module which allows one to rename constructors to another name and the '%template(Foo) ...' does not rename the constructors back to Foo, so the constructors end up as initialisation methods called 'Foo_' instead. I'll see if I can fix this in a future version, but for now, you can work around it for the Python module, by renaming just the constructors back to Foo. The example below should give you a fully functioning proxy class called Foo: %rename(Foo_) Foo; %rename(Foo) Foo<float>::Foo; %inline %{ template<typename T> class Foo { public: Foo() {} Foo(int i) {} }; %} %template(Foo) Foo<float>; William |
From: Ben W. <be...@sa...> - 2009-04-21 02:42:11
|
William S Fulton wrote: ... > Sorry, I used the Java module and there everything works as expected. > The '%rename(Foo_) Foo' is a global rename, so it renames both the class > and the constructors. Then there is a quirk in the Python module which > allows one to rename constructors to another name and the > '%template(Foo) ...' does not rename the constructors back to Foo, so > the constructors end up as initialisation methods called 'Foo_' instead. > I'll see if I can fix this in a future version, but for now, you can > work around it for the Python module, by renaming just the constructors > back to Foo. The example below should give you a fully functioning proxy > class called Foo: Thanks very much - that works perfectly. I can't make it work though if my class Foo lives in the 'bar' namespace. How should the renames and %templates be qualified (if at all) to work with the namespace? Ben -- be...@sa... http://salilab.org/~ben/ "It is a capital mistake to theorize before one has data." - Sir Arthur Conan Doyle |
From: William S F. <ws...@fu...> - 2009-04-21 18:30:04
|
Ben Webb wrote: > William S Fulton wrote: > ... >> Sorry, I used the Java module and there everything works as expected. >> The '%rename(Foo_) Foo' is a global rename, so it renames both the class >> and the constructors. Then there is a quirk in the Python module which >> allows one to rename constructors to another name and the >> '%template(Foo) ...' does not rename the constructors back to Foo, so >> the constructors end up as initialisation methods called 'Foo_' instead. >> I'll see if I can fix this in a future version, but for now, you can >> work around it for the Python module, by renaming just the constructors >> back to Foo. The example below should give you a fully functioning proxy >> class called Foo: > > Thanks very much - that works perfectly. I can't make it work though if > my class Foo lives in the 'bar' namespace. How should the renames and > %templates be qualified (if at all) to work with the namespace? Mmmm, I can't get this to work either. Please log a bug in the bugtracker. Some non-perfect workarounds: %rename(Foo_) bar::Foo<float>; %inline %{ namespace bar { template<typename T> class Foo { public: Foo() {} Foo(int i) {} }; } %} %template(Foo) bar::Foo<float>; You can call Foo(-1) to create the class, but if you look at the proxy class name, it is Foo_. %inline %{ #define Foo FooRenamed %} %inline %{ namespace bar { template<typename T> class Foo { public: Foo() {} Foo(int i) {} }; } %} %template(Foo) bar::FooRenamed<float>; This gives you a Foo proxy class, but when displaying it, it uses the renamed name: <example.Foo; proxy of <Swig Object of type 'bar::FooRenamed< float > *' at 0xb7d718c0> > William |
From: Ben W. <be...@sa...> - 2009-04-22 00:36:08
|
William S Fulton wrote: > Ben Webb wrote: ... >> Thanks very much - that works perfectly. I can't make it work though if >> my class Foo lives in the 'bar' namespace. How should the renames and >> %templates be qualified (if at all) to work with the namespace? > > Mmmm, I can't get this to work either. Please log a bug in the > bugtracker. OK - opened as #2778184. Ben -- be...@sa... http://salilab.org/~ben/ "It is a capital mistake to theorize before one has data." - Sir Arthur Conan Doyle |