Applying typemaps "on demand"

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Applying typemaps "on demand"

nerochiaro (Bugzilla)
Hello,
I'm rather new to SWIG and trying to write Ruby bindings for a C++ library.
I have a std::vector-like template class that I have successfully
wrapped so far.
The only problem comes when I try to extend it to create a function
that implements the typical "each" ruby iterator method. For non-ruby
programmers, what it does is to iterate across all elements of the
vector and call the ruby API function rb_yield(item) for each one.
The problem lies in the fact that rb_yield expects a ruby object as
input parameter (type VALUE).
The following code works, but has a problem (see below):

template <class ELEM> class MyList
{
public:
        %extend {
                void each() {
                        MyList<ELEM>::ConstIterator i;
                        for (i=self->begin(); i!=self->end(); ++i)
                                        rb_yield(SWIG_NewPointerObj((void *) &(*i), $descriptor(ELEM *), 0));
                }
        }
}

The problem is that if there are typemaps defined for the ELEM type
they won't get applied by SWIG_NewPointerObj.
       
I could simply provide a different implementation of each() for any
specialization that have a typemap defined for, but that gets old very
fast and kind of misses the point of using templates in the first
place.

So I was wondering if there was a more elegant (== automated) way to do it.
What I'm looking for is something that works like SWIG_NewPointerObj
but that also applies typemaps.
Does something like that exist ? If not, can anyone suggest alternatives ?

Thanks in advance.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Marcelo Matus
Yes, grab the last cvs version and do

%extend  {

void each() {
 static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
 MyList<ELEM>::ConstIterator i;
 for (i=self->begin(); i!=self->end(); ++i)
    rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
  }

}

nerochiaro wrote:

>Hello,
>I'm rather new to SWIG and trying to write Ruby bindings for a C++ library.
>I have a std::vector-like template class that I have successfully
>wrapped so far.
>The only problem comes when I try to extend it to create a function
>that implements the typical "each" ruby iterator method. For non-ruby
>programmers, what it does is to iterate across all elements of the
>vector and call the ruby API function rb_yield(item) for each one.
>The problem lies in the fact that rb_yield expects a ruby object as
>input parameter (type VALUE).
>The following code works, but has a problem (see below):
>
>template <class ELEM> class MyList
>{
>public:
> %extend {
> void each() {
> MyList<ELEM>::ConstIterator i;
> for (i=self->begin(); i!=self->end(); ++i)
> rb_yield(SWIG_NewPointerObj((void *) &(*i), $descriptor(ELEM *), 0));
> }
> }
>}
>
>The problem is that if there are typemaps defined for the ELEM type
>they won't get applied by SWIG_NewPointerObj.
>
>I could simply provide a different implementation of each() for any
>specialization that have a typemap defined for, but that gets old very
>fast and kind of misses the point of using templates in the first
>place.
>
>So I was wondering if there was a more elegant (== automated) way to do it.
>What I'm looking for is something that works like SWIG_NewPointerObj
>but that also applies typemaps.
>Does something like that exist ? If not, can anyone suggest alternatives ?
>
>Thanks in advance.
>
>
>-------------------------------------------------------
>This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
>for problems?  Stop!  Download the new AJAX search engine that makes
>searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
><a href="http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642
>_______________________________________________
>Swig-user mailing list
>[hidden email]
>https://lists.sourceforge.net/lists/listinfo/swig-user
>
>  
>



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Charlie Savage
Doesn't the proposed code:

static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));

Do the same thing as the original?

rb_yield(SWIG_NewPointerObj((void *) &(*i), $descriptor(ELEM *), 0));

Which is get the SWIG descriptor for ELEM* and pass it to the
SWIG_NewPointerObj method?

I think the question is what if you have a typemap like this:

%typemap(out) ELEM* {
 ....
}

How can it be applied within the rb_yield in an automated way?  I would
say that if you have %typemap(out) ELEM* that you define it using a
fragment, and then call that fragment from your code.  But that's not
automated, unless you do some fancy macro programming.  Maybe there is a
better way.

Out of curiosity, which C++ library are you trying to wrap?

Thanks,

Charlie

Marcelo Matus wrote:

> Yes, grab the last cvs version and do
>
> %extend  {
>
> void each() {
> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
> MyList<ELEM>::ConstIterator i;
> for (i=self->begin(); i!=self->end(); ++i)
>    rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>  }
>
> }
>
> nerochiaro wrote:
>
>> Hello,
>> I'm rather new to SWIG and trying to write Ruby bindings for a C++
>> library.
>> I have a std::vector-like template class that I have successfully
>> wrapped so far.
>> The only problem comes when I try to extend it to create a function
>> that implements the typical "each" ruby iterator method. For non-ruby
>> programmers, what it does is to iterate across all elements of the
>> vector and call the ruby API function rb_yield(item) for each one.
>> The problem lies in the fact that rb_yield expects a ruby object as
>> input parameter (type VALUE).
>> The following code works, but has a problem (see below):
>>
>> template <class ELEM> class MyList
>> {
>> public:
>>     %extend {
>>         void each() {
>>             MyList<ELEM>::ConstIterator i;
>>             for (i=self->begin(); i!=self->end(); ++i)
>>                     rb_yield(SWIG_NewPointerObj((void *) &(*i),
>> $descriptor(ELEM *), 0));
>>         }
>>     }
>> }
>>
>> The problem is that if there are typemaps defined for the ELEM type
>> they won't get applied by SWIG_NewPointerObj.
>>    
>> I could simply provide a different implementation of each() for any
>> specialization that have a typemap defined for, but that gets old very
>> fast and kind of misses the point of using templates in the first
>> place.
>>
>> So I was wondering if there was a more elegant (== automated) way to
>> do it.
>> What I'm looking for is something that works like SWIG_NewPointerObj
>> but that also applies typemaps.
>> Does something like that exist ? If not, can anyone suggest
>> alternatives ?
>>
>> Thanks in advance.
>>
>>
>> -------------------------------------------------------
>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>> log files
>> for problems?  Stop!  Download the new AJAX search engine that makes
>> searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
>> <a href="http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642
>> _______________________________________________
>> Swig-user mailing list
>> [hidden email]
>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>
>>  
>>
>
>
>
> -------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc. Do you grep through log
> files
> for problems?  Stop!  Download the new AJAX search engine that makes
> searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
> <a href="http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642
> _______________________________________________
> Swig-user mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/swig-user
>
>

smime.p7s (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Marcelo Matus
Well, in theory yes, in the practice no, since $descriptor is only
expanded inside
a typemap, not inside an %extend cdecl.  That makes SWIG_NewPointerObj
to fail,
SWIG_TypeQuery in the other hand, works fine outside a typemap.

Anyway if a %typemap(out) ELEM * {} is needed, just define it as

%extend  {
    %typemap(out) ELEM * {...}
}

you can even define the extend outside the class declaration:

%extend  MyList {
    %typemap(out) ELEM * {...}
}

template <class Elem>
class MyList {
   ...
};

and MyList can even be defined in a separated .h file, as usual. But, you
need the last swig CVS version.

Check for example

   Lib/std/std_carray.swg
   Lib/python/std_carray.i
   Examples/test-suite/python/li_std_carray.i

for more ideas about mixing %extend + %typemaps + templates.

This is a small example (that only wok with 1.3.28) that shows several
concepts that will be used in the next STD/STL support for the
UTL(python,perl,tcl,ruby).

Marcelo




Charlie Savage wrote:

> Doesn't the proposed code:
>
> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
> rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>
> Do the same thing as the original?
>
> rb_yield(SWIG_NewPointerObj((void *) &(*i), $descriptor(ELEM *), 0));
>
> Which is get the SWIG descriptor for ELEM* and pass it to the
> SWIG_NewPointerObj method?
>
> I think the question is what if you have a typemap like this:
>
> %typemap(out) ELEM* {
> ....
> }
>
> How can it be applied within the rb_yield in an automated way?  I
> would say that if you have %typemap(out) ELEM* that you define it
> using a fragment, and then call that fragment from your code.  But
> that's not automated, unless you do some fancy macro programming.  
> Maybe there is a better way.
>
> Out of curiosity, which C++ library are you trying to wrap?
>
> Thanks,
>
> Charlie
>
> Marcelo Matus wrote:
>
>> Yes, grab the last cvs version and do
>>
>> %extend  {
>>
>> void each() {
>> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
>> MyList<ELEM>::ConstIterator i;
>> for (i=self->begin(); i!=self->end(); ++i)
>>    rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>>  }
>>
>> }
>>
>> nerochiaro wrote:
>>
>>> Hello,
>>> I'm rather new to SWIG and trying to write Ruby bindings for a C++
>>> library.
>>> I have a std::vector-like template class that I have successfully
>>> wrapped so far.
>>> The only problem comes when I try to extend it to create a function
>>> that implements the typical "each" ruby iterator method. For non-ruby
>>> programmers, what it does is to iterate across all elements of the
>>> vector and call the ruby API function rb_yield(item) for each one.
>>> The problem lies in the fact that rb_yield expects a ruby object as
>>> input parameter (type VALUE).
>>> The following code works, but has a problem (see below):
>>>
>>> template <class ELEM> class MyList
>>> {
>>> public:
>>>     %extend {
>>>         void each() {
>>>             MyList<ELEM>::ConstIterator i;
>>>             for (i=self->begin(); i!=self->end(); ++i)
>>>                     rb_yield(SWIG_NewPointerObj((void *) &(*i),
>>> $descriptor(ELEM *), 0));
>>>         }
>>>     }
>>> }
>>>
>>> The problem is that if there are typemaps defined for the ELEM type
>>> they won't get applied by SWIG_NewPointerObj.
>>>     I could simply provide a different implementation of each() for any
>>> specialization that have a typemap defined for, but that gets old very
>>> fast and kind of misses the point of using templates in the first
>>> place.
>>>
>>> So I was wondering if there was a more elegant (== automated) way to
>>> do it.
>>> What I'm looking for is something that works like SWIG_NewPointerObj
>>> but that also applies typemaps.
>>> Does something like that exist ? If not, can anyone suggest
>>> alternatives ?
>>>
>>> Thanks in advance.
>>>
>>>
>>> -------------------------------------------------------
>>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>>> log files
>>> for problems?  Stop!  Download the new AJAX search engine that makes
>>> searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
>>> <a href="http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642
>>> _______________________________________________
>>> Swig-user mailing list
>>> [hidden email]
>>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>>
>>>  
>>>
>>
>>
>>
>> -------------------------------------------------------
>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>> log files
>> for problems?  Stop!  Download the new AJAX search engine that makes
>> searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
>> <a href="http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642
>> _______________________________________________
>> Swig-user mailing list
>> [hidden email]
>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>
>>



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

nerochiaro (Bugzilla)
I tried Marcelo's suggestion and reimplemented the each() method this way:

template <class ELEM> class MyList
{
public:
        %extend {
                void each() {
                        static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
                        MyList::ConstIterator i;
                        for (i=self->begin(); i!=self->end(); ++i) {
                                VALUE x = SWIG_NewPointerObj((void *) &(*i), desc, 0);
                                rb_yield(x);
                        }
                }
        }
}

This code causes a crash when called, and the crash happens at the
call to SWIG_NewPointerObj.
I might be doing something wrong. If so, please let me know.

> Anyway if a %typemap(out) ELEM * {} is needed, just define it as
>
> %extend  {
>     %typemap(out) ELEM * {...}
> }

The typemap is already defined in the interface.
My problem is that in this case SWIG cannot apply it automatically :
I'm not returning anything from the each() method...so there's no
"out" to apply the out typemap to.

That's why I want to apply the typemap "on demand" inside the function.
Also look at the response to Charlie Savage's message for more info on
what the problem really is.

> Check for example
>
>    Lib/std/std_carray.swg
>    Lib/python/std_carray.i
>    Examples/test-suite/python/li_std_carray.i
>
> for more ideas about mixing %extend + %typemaps + templates.

I have looked into the samples you proposed. I must admit my skill
with STL and templates wasn't good enough to understand everything in
these files.
But it looks to me that none of these examples address the problem I'm
trying to solve here -- or i wasn't good enough to find it.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

nerochiaro (Bugzilla)
In reply to this post by Charlie Savage
> Doesn't the proposed code do the same thing as the original?
> Which is get the SWIG descriptor for ELEM* and pass it to the
> SWIG_NewPointerObj method?

I could not try it because it generated a crash (see also my reply to
Marcelo's message), but it looks to me like you are right: it seem to
do the same thing i was doing.

> I think the question is what if you have a typemap like this:
> %typemap(out) ELEM* {  .... }
> How can it be applied within the rb_yield in an automated way?

You are right: that's exactly my problem.

> I would say that if you have %typemap(out) ELEM* that you define it using a
> fragment, and then call that fragment from your code.  But that's not
> automated, unless you do some fancy macro programming.  Maybe there is a
> better way.

What do you mean with "fragment" ?
A function ? Or the %fragment thing I've seen in some files inside
swig/lib/std ?
If you mean the latter, then can you point me to documentation for it,
because I couldn't find it anywhere.

> Out of curiosity, which C++ library are you trying to wrap?

I'm wrapping TagLib, a library for working with audio metadata.
See http://developer.kde.org/~wheeler/taglib.html for more info.
They seem to lack Ruby bindings, and I seem to lack a good tagging
library for Ruby, so I'm wrapping it.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Marcelo Matus
In reply to this post by nerochiaro (Bugzilla)
Did you instantiate the template?, for example


   %template(MyList_int) MyList<int>;

are you using the swig CVS version?, if you have the swig CVS version,
what do you see if you run using -dump_module

   swig -dump_module -c++ ....

what is the error you are getting?,
can you dig in the wrapped file and see if there is any code generated
for 'each',
look for something like MyClass_int_each. Can you cut/paste the
generated code?


Marcelo

nerochiaro wrote:

>I tried Marcelo's suggestion and reimplemented the each() method this way:
>
>template <class ELEM> class MyList
>{
>public:
> %extend {
> void each() {
> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
> MyList::ConstIterator i;
> for (i=self->begin(); i!=self->end(); ++i) {
> VALUE x = SWIG_NewPointerObj((void *) &(*i), desc, 0);
> rb_yield(x);
> }
> }
> }
>}
>
>This code causes a crash when called, and the crash happens at the
>call to SWIG_NewPointerObj.
>I might be doing something wrong. If so, please let me know.
>
>  
>
>>Anyway if a %typemap(out) ELEM * {} is needed, just define it as
>>
>>%extend  {
>>    %typemap(out) ELEM * {...}
>>}
>>    
>>
>
>The typemap is already defined in the interface.
>My problem is that in this case SWIG cannot apply it automatically :
>I'm not returning anything from the each() method...so there's no
>"out" to apply the out typemap to.
>
>That's why I want to apply the typemap "on demand" inside the function.
>Also look at the response to Charlie Savage's message for more info on
>what the problem really is.
>
>  
>
>>Check for example
>>
>>   Lib/std/std_carray.swg
>>   Lib/python/std_carray.i
>>   Examples/test-suite/python/li_std_carray.i
>>
>>for more ideas about mixing %extend + %typemaps + templates.
>>    
>>
>
>I have looked into the samples you proposed. I must admit my skill
>with STL and templates wasn't good enough to understand everything in
>these files.
>But it looks to me that none of these examples address the problem I'm
>trying to solve here -- or i wasn't good enough to find it.
>
>  
>



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Charlie Savage
In reply to this post by Marcelo Matus
That's clever.

Marcelo, any chance you can update the SWIG documentation to show
examples of all these tricks?   In fact, I think it would be great to
have a significantly update the typemaps section with plenty of examples
like these, plus lots of examples of using the new unified typemaps
(which I find a bit hard to wrap my mind a round).  In fact, maybe just
a full chapter, with examples that use the new typemaps since those
would be applicable to multiple languages.  Then we could remove some of
the examples from the Ruby/Python/TCL/Perl sections and move them into
this new section.  It should be "cookbook" style - thus "If you want to
wrap vectors of pointers then do this"

Charlie

Marcelo Matus wrote:

> Well, in theory yes, in the practice no, since $descriptor is only
> expanded inside
> a typemap, not inside an %extend cdecl.  That makes SWIG_NewPointerObj
> to fail,
> SWIG_TypeQuery in the other hand, works fine outside a typemap.
>
> Anyway if a %typemap(out) ELEM * {} is needed, just define it as
>
> %extend  {
>    %typemap(out) ELEM * {...}
> }
>
> you can even define the extend outside the class declaration:
>
> %extend  MyList {
>    %typemap(out) ELEM * {...}
> }
>
> template <class Elem>
> class MyList {
>   ...
> };
>
> and MyList can even be defined in a separated .h file, as usual. But, you
> need the last swig CVS version.
>
> Check for example
>
>   Lib/std/std_carray.swg
>   Lib/python/std_carray.i
>   Examples/test-suite/python/li_std_carray.i
>
> for more ideas about mixing %extend + %typemaps + templates.
>
> This is a small example (that only wok with 1.3.28) that shows several
> concepts that will be used in the next STD/STL support for the
> UTL(python,perl,tcl,ruby).
>
> Marcelo
>
>
>
>
> Charlie Savage wrote:
>
>> Doesn't the proposed code:
>>
>> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
>> rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>>
>> Do the same thing as the original?
>>
>> rb_yield(SWIG_NewPointerObj((void *) &(*i), $descriptor(ELEM *), 0));
>>
>> Which is get the SWIG descriptor for ELEM* and pass it to the
>> SWIG_NewPointerObj method?
>>
>> I think the question is what if you have a typemap like this:
>>
>> %typemap(out) ELEM* {
>> ....
>> }
>>
>> How can it be applied within the rb_yield in an automated way?  I
>> would say that if you have %typemap(out) ELEM* that you define it
>> using a fragment, and then call that fragment from your code.  But
>> that's not automated, unless you do some fancy macro programming.  
>> Maybe there is a better way.
>>
>> Out of curiosity, which C++ library are you trying to wrap?
>>
>> Thanks,
>>
>> Charlie
>>
>> Marcelo Matus wrote:
>>
>>> Yes, grab the last cvs version and do
>>>
>>> %extend  {
>>>
>>> void each() {
>>> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
>>> MyList<ELEM>::ConstIterator i;
>>> for (i=self->begin(); i!=self->end(); ++i)
>>>    rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>>>  }
>>>
>>> }
>>>
>>> nerochiaro wrote:
>>>
>>>> Hello,
>>>> I'm rather new to SWIG and trying to write Ruby bindings for a C++
>>>> library.
>>>> I have a std::vector-like template class that I have successfully
>>>> wrapped so far.
>>>> The only problem comes when I try to extend it to create a function
>>>> that implements the typical "each" ruby iterator method. For non-ruby
>>>> programmers, what it does is to iterate across all elements of the
>>>> vector and call the ruby API function rb_yield(item) for each one.
>>>> The problem lies in the fact that rb_yield expects a ruby object as
>>>> input parameter (type VALUE).
>>>> The following code works, but has a problem (see below):
>>>>
>>>> template <class ELEM> class MyList
>>>> {
>>>> public:
>>>>     %extend {
>>>>         void each() {
>>>>             MyList<ELEM>::ConstIterator i;
>>>>             for (i=self->begin(); i!=self->end(); ++i)
>>>>                     rb_yield(SWIG_NewPointerObj((void *) &(*i),
>>>> $descriptor(ELEM *), 0));
>>>>         }
>>>>     }
>>>> }
>>>>
>>>> The problem is that if there are typemaps defined for the ELEM type
>>>> they won't get applied by SWIG_NewPointerObj.
>>>>     I could simply provide a different implementation of each() for
>>>> any
>>>> specialization that have a typemap defined for, but that gets old very
>>>> fast and kind of misses the point of using templates in the first
>>>> place.
>>>>
>>>> So I was wondering if there was a more elegant (== automated) way
>>>> to do it.
>>>> What I'm looking for is something that works like SWIG_NewPointerObj
>>>> but that also applies typemaps.
>>>> Does something like that exist ? If not, can anyone suggest
>>>> alternatives ?
>>>>
>>>> Thanks in advance.
>>>>
>>>>
>>>> -------------------------------------------------------
>>>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>>>> log files
>>>> for problems?  Stop!  Download the new AJAX search engine that makes
>>>> searching your log files as easy as surfing the  web.  DOWNLOAD
>>>> SPLUNK!
>>>> <a href="http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642
>>>> _______________________________________________
>>>> Swig-user mailing list
>>>> [hidden email]
>>>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>>>
>>>>  
>>>>
>>>
>>>
>>>
>>> -------------------------------------------------------
>>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>>> log files
>>> for problems?  Stop!  Download the new AJAX search engine that makes
>>> searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
>>> <a href="http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642
>>> _______________________________________________
>>> Swig-user mailing list
>>> [hidden email]
>>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>>
>>>
>
>
>

smime.p7s (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

nerochiaro (Bugzilla)
In reply to this post by Marcelo Matus
> Did you instantiate the template?, for example
>    %template(MyList_int) MyList<int>;

Yes, I instantiate it like this:

%template(StringListBase) MyList<TagLib::String>;

> are you using the swig CVS version?, if you have the swig CVS version,
> what do you see if you run using -dump_module
>
>    swig -dump_module -c++ ....

I have trimmed down the interface file to wrap only the classes
relevant to our discussion, but the
output from -dump_module is still fairly large.
To avoid clogging the list, I have posted it at http://swig.pastebin.com/510642

> what is the error you are getting?,

The error I'm getting is simply a segfault. My quick ruby test script
crashes on the call to SWIG_NewPointerObj inside the wrapper for
each().
I would gladly provide a stack trace or other debug information but
I'm not sure how to produce them.

> can you dig in the wrapped file and see if there is any code generated
> for 'each', look for something like MyClass_int_each. Can you cut/paste the
> generated code?

Sure, here's what I think are the relevant functions. If you think
something is missing, let me know:

/******************************************************************************/

SWIGINTERN void TagLib_List_Sl_int_Sg__each(TagLib::List<int > *self){
                                static swig_type_info *desc = SWIG_TypeQuery("int" " *");
                                TagLib::List<int>::ConstIterator i;
                                for (i=self->begin(); i!=self->end(); ++i)
                                {
                                        VALUE x = SWIG_NewPointerObj((void *) &(*i), desc, 0);
                                        rb_yield(x);
                                }
                        }

SWIGINTERN VALUE
_wrap_StringListBase_each(int argc, VALUE *argv, VALUE self) {
  TagLib::List<TagLib::String > *arg1 = (TagLib::List<TagLib::String > *) 0 ;
  void *argp1 = 0 ;
  int res1 ;

  if ((argc < 0) || (argc > 0)) {
    rb_raise(rb_eArgError, "wrong # of arguments(%d for 0)",argc); SWIG_fail;
  }
  res1 = SWIG_ConvertPtr(self,
&argp1,SWIGTYPE_p_TagLib__ListTTagLib__String_t, 0 |  0 );
  if (!SWIG_IsOK(res1)) {
    SWIG_exception_fail(((res1 != SWIG_ERROR) ? res1 :
SWIG_TypeError), "in method '" "each" "', argument " "1"" of type '"
"TagLib::List<TagLib::String > *""'");
  }
  arg1 = reinterpret_cast<TagLib::List<TagLib::String > * >(argp1);
  TagLib_List_Sl_TagLib_String_Sg__each(arg1);

  return Qnil;
fail:
  return Qnil;
}

/*****************************************************************************/

That should be it. If you think something is missing, let me know and
I'll post it.
And thanks for the help so far.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Marcelo Matus
I see your problem, you are wrapping "primitive" types (int, double, etc).

The SWIG_NewPointerObj/SWIG_TypeQuery methods are needed when you
wrap 'user types', as classes, not primitive types.

In your case we need to use some tricks that are currently in the
process of been
released in a formal way, ie, they are obscure and undocumented, as the
ugly templates
you saw in the std_carrys.swg file, and worse, right now they are only
available for
python.

In short, instead of calling SWIG_NewPointerObj, you need to call
methods which are defined as

   SWIG_From(int), SWIG_From(double), etc.

which translate primitive types into VALUE types. These names are really
macros which generate names
as

    SWIG_From_int, SWIG_From_double

maybe a temporal solution for you, as long you use only primitive types,
will be using

   VALUE x = SWIG_From_#@ELEM((*i));
   rb_yield(x);


But this is a very very temporal, and only works for primitive types.
The other idea is to use
macros:

%define %specialize_mylist(Name, Type, FromMethod)
%extend MyList<Type> {
void each() {
  MyList::ConstIterator i;
   for (i=self->begin(); i!=self->end(); ++i) {
       VALUE x = FromMethod((Type)(*i));
        rb_yield(x);

 }
}
}
%template(Name) MyList<Type>;
%enddef


and  use it as

%specialize_mylist(MyList_int, int, SWIG_From(int))
%specialize_mylist(MyList_double, double, SWIG_From(double))


Similarly, you can define a macro as %specialize_mylist_ptr for pointer
types and so on,
as it is used right now in ruby and the std/stl support.

Marcelo


nerochiaro wrote:

>>Did you instantiate the template?, for example
>>   %template(MyList_int) MyList<int>;
>>    
>>
>
>Yes, I instantiate it like this:
>
>%template(StringListBase) MyList<TagLib::String>;
>
>  
>
>>are you using the swig CVS version?, if you have the swig CVS version,
>>what do you see if you run using -dump_module
>>
>>   swig -dump_module -c++ ....
>>    
>>
>
>I have trimmed down the interface file to wrap only the classes
>relevant to our discussion, but the
>output from -dump_module is still fairly large.
>To avoid clogging the list, I have posted it at http://swig.pastebin.com/510642
>
>  
>
>>what is the error you are getting?,
>>    
>>
>
>The error I'm getting is simply a segfault. My quick ruby test script
>crashes on the call to SWIG_NewPointerObj inside the wrapper for
>each().
>I would gladly provide a stack trace or other debug information but
>I'm not sure how to produce them.
>
>  
>
>>can you dig in the wrapped file and see if there is any code generated
>>for 'each', look for something like MyClass_int_each. Can you cut/paste the
>>generated code?
>>    
>>
>
>Sure, here's what I think are the relevant functions. If you think
>something is missing, let me know:
>
>/******************************************************************************/
>
>SWIGINTERN void TagLib_List_Sl_int_Sg__each(TagLib::List<int > *self){
> static swig_type_info *desc = SWIG_TypeQuery("int" " *");
> TagLib::List<int>::ConstIterator i;
> for (i=self->begin(); i!=self->end(); ++i)
> {
> VALUE x = SWIG_NewPointerObj((void *) &(*i), desc, 0);
> rb_yield(x);
> }
> }
>
>SWIGINTERN VALUE
>_wrap_StringListBase_each(int argc, VALUE *argv, VALUE self) {
>  TagLib::List<TagLib::String > *arg1 = (TagLib::List<TagLib::String > *) 0 ;
>  void *argp1 = 0 ;
>  int res1 ;
>
>  if ((argc < 0) || (argc > 0)) {
>    rb_raise(rb_eArgError, "wrong # of arguments(%d for 0)",argc); SWIG_fail;
>  }
>  res1 = SWIG_ConvertPtr(self,
>&argp1,SWIGTYPE_p_TagLib__ListTTagLib__String_t, 0 |  0 );
>  if (!SWIG_IsOK(res1)) {
>    SWIG_exception_fail(((res1 != SWIG_ERROR) ? res1 :
>SWIG_TypeError), "in method '" "each" "', argument " "1"" of type '"
>"TagLib::List<TagLib::String > *""'");
>  }
>  arg1 = reinterpret_cast<TagLib::List<TagLib::String > * >(argp1);
>  TagLib_List_Sl_TagLib_String_Sg__each(arg1);
>
>  return Qnil;
>fail:
>  return Qnil;
>}
>
>/*****************************************************************************/
>
>That should be it. If you think something is missing, let me know and
>I'll post it.
>And thanks for the help so far.
>
>  
>



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Marcelo Matus
In reply to this post by Charlie Savage
The problem now is that all the template things around that example, and
the STD/STL support
in python, will probably change since I am waiting 1.3.28 to be out to
start working in unifying
the STD/STL support, using similar techniques, inside the UTL. Then we
will have the same
support/classes we have in the STD/STL for python in all the other
languages that use the
UTL, including standard ways to wrap vectors, arrays and so on.

So, if there is time, I will try better to add more docs in the "first
part" of the UTL, ie
typemaps and support for simple types, which use the idioms or either
'by value' or 'pointer' types.

In the long term the UTL should support

1.- By value types [done]: as int, double, short, float, etc, which can
be used as follow:

      int foo(int);

2.- Pointers types [done], as virtual classes and others types which
can't (or are not recommended to)
     be used as simple 'by value' types, and usually are used as:

       MyClass *foo(MyClass *);

3.- Strings [*done]: generalization of the C strings, or the  'char *'
type, but considering
     different kind of characters, as wchar_t, UTF8_t, TCL_UChar *, etc.
Also known as arrays
     with a null char terminator.

     * it is someway done in the current STL, but it will be changed to
accept different kind
        of Char types in a simpler way.

3.- C Sequences[not yet]: simple C sequences as 'double vector[100]'

4.- General C++ sequences[not yet]:  for example  template<class T> Vector;

5.- STL/STD support as general C++ sequences [not yet, but working in
python]: as std::vector, std::list, etc.


Marcelo

Charlie Savage wrote:

> That's clever.
>
> Marcelo, any chance you can update the SWIG documentation to show
> examples of all these tricks?   In fact, I think it would be great to
> have a significantly update the typemaps section with plenty of
> examples like these, plus lots of examples of using the new unified
> typemaps (which I find a bit hard to wrap my mind a round).  In fact,
> maybe just a full chapter, with examples that use the new typemaps
> since those would be applicable to multiple languages.  Then we could
> remove some of the examples from the Ruby/Python/TCL/Perl sections and
> move them into this new section.  It should be "cookbook" style - thus
> "If you want to wrap vectors of pointers then do this"
>
> Charlie
>
> Marcelo Matus wrote:
>
>> Well, in theory yes, in the practice no, since $descriptor is only
>> expanded inside
>> a typemap, not inside an %extend cdecl.  That makes
>> SWIG_NewPointerObj to fail,
>> SWIG_TypeQuery in the other hand, works fine outside a typemap.
>>
>> Anyway if a %typemap(out) ELEM * {} is needed, just define it as
>>
>> %extend  {
>>    %typemap(out) ELEM * {...}
>> }
>>
>> you can even define the extend outside the class declaration:
>>
>> %extend  MyList {
>>    %typemap(out) ELEM * {...}
>> }
>>
>> template <class Elem>
>> class MyList {
>>   ...
>> };
>>
>> and MyList can even be defined in a separated .h file, as usual. But,
>> you
>> need the last swig CVS version.
>>
>> Check for example
>>
>>   Lib/std/std_carray.swg
>>   Lib/python/std_carray.i
>>   Examples/test-suite/python/li_std_carray.i
>>
>> for more ideas about mixing %extend + %typemaps + templates.
>>
>> This is a small example (that only wok with 1.3.28) that shows several
>> concepts that will be used in the next STD/STL support for the
>> UTL(python,perl,tcl,ruby).
>>
>> Marcelo
>>
>>
>>
>>
>> Charlie Savage wrote:
>>
>>> Doesn't the proposed code:
>>>
>>> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
>>> rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>>>
>>> Do the same thing as the original?
>>>
>>> rb_yield(SWIG_NewPointerObj((void *) &(*i), $descriptor(ELEM *), 0));
>>>
>>> Which is get the SWIG descriptor for ELEM* and pass it to the
>>> SWIG_NewPointerObj method?
>>>
>>> I think the question is what if you have a typemap like this:
>>>
>>> %typemap(out) ELEM* {
>>> ....
>>> }
>>>
>>> How can it be applied within the rb_yield in an automated way?  I
>>> would say that if you have %typemap(out) ELEM* that you define it
>>> using a fragment, and then call that fragment from your code.  But
>>> that's not automated, unless you do some fancy macro programming.  
>>> Maybe there is a better way.
>>>
>>> Out of curiosity, which C++ library are you trying to wrap?
>>>
>>> Thanks,
>>>
>>> Charlie
>>>
>>> Marcelo Matus wrote:
>>>
>>>> Yes, grab the last cvs version and do
>>>>
>>>> %extend  {
>>>>
>>>> void each() {
>>>> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
>>>> MyList<ELEM>::ConstIterator i;
>>>> for (i=self->begin(); i!=self->end(); ++i)
>>>>    rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>>>>  }
>>>>
>>>> }
>>>>
>>>> nerochiaro wrote:
>>>>
>>>>> Hello,
>>>>> I'm rather new to SWIG and trying to write Ruby bindings for a C++
>>>>> library.
>>>>> I have a std::vector-like template class that I have successfully
>>>>> wrapped so far.
>>>>> The only problem comes when I try to extend it to create a function
>>>>> that implements the typical "each" ruby iterator method. For non-ruby
>>>>> programmers, what it does is to iterate across all elements of the
>>>>> vector and call the ruby API function rb_yield(item) for each one.
>>>>> The problem lies in the fact that rb_yield expects a ruby object as
>>>>> input parameter (type VALUE).
>>>>> The following code works, but has a problem (see below):
>>>>>
>>>>> template <class ELEM> class MyList
>>>>> {
>>>>> public:
>>>>>     %extend {
>>>>>         void each() {
>>>>>             MyList<ELEM>::ConstIterator i;
>>>>>             for (i=self->begin(); i!=self->end(); ++i)
>>>>>                     rb_yield(SWIG_NewPointerObj((void *) &(*i),
>>>>> $descriptor(ELEM *), 0));
>>>>>         }
>>>>>     }
>>>>> }
>>>>>
>>>>> The problem is that if there are typemaps defined for the ELEM type
>>>>> they won't get applied by SWIG_NewPointerObj.
>>>>>     I could simply provide a different implementation of each()
>>>>> for any
>>>>> specialization that have a typemap defined for, but that gets old
>>>>> very
>>>>> fast and kind of misses the point of using templates in the first
>>>>> place.
>>>>>
>>>>> So I was wondering if there was a more elegant (== automated) way
>>>>> to do it.
>>>>> What I'm looking for is something that works like SWIG_NewPointerObj
>>>>> but that also applies typemaps.
>>>>> Does something like that exist ? If not, can anyone suggest
>>>>> alternatives ?
>>>>>
>>>>> Thanks in advance.
>>>>>
>>>>>
>>>>> -------------------------------------------------------
>>>>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>>>>> log files
>>>>> for problems?  Stop!  Download the new AJAX search engine that makes
>>>>> searching your log files as easy as surfing the  web.  DOWNLOAD
>>>>> SPLUNK!
>>>>> <a href="http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642
>>>>> _______________________________________________
>>>>> Swig-user mailing list
>>>>> [hidden email]
>>>>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>>>>
>>>>>  
>>>>>
>>>>
>>>>
>>>>
>>>> -------------------------------------------------------
>>>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>>>> log files
>>>> for problems?  Stop!  Download the new AJAX search engine that makes
>>>> searching your log files as easy as surfing the  web.  DOWNLOAD
>>>> SPLUNK!
>>>> <a href="http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642
>>>> _______________________________________________
>>>> Swig-user mailing list
>>>> [hidden email]
>>>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>>>
>>>>
>>
>>
>>



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

nerochiaro (Bugzilla)
In reply to this post by Marcelo Matus
> I see your problem, you are wrapping "primitive" types (int, double, etc).
>
> The SWIG_NewPointerObj/SWIG_TypeQuery methods are needed when you
> wrap 'user types', as classes, not primitive types.

I have to apologize here. Looking at the code I posted in my previous
message I noticed that I had pasted one of the two functions wrong.
That function wrapping an int was just a test that i later removed.
The true function that causes the problem is the following:

SWIGINTERN void
TagLib_List_Sl_TagLib_String_Sg__each(TagLib::List<TagLib::String >
*self){
        static swig_type_info *desc = SWIG_TypeQuery("TagLib::String" " *");
        TagLib::List<TagLib::String>::ConstIterator i;
        for (i=self->begin(); i!=self->end(); ++i)
        {
                VALUE x = SWIG_NewPointerObj((void *) &(*i), desc, 0);
                rb_yield(x);
        }
}

Which uses a pointer type (TagLib::String), for which I already
defined a typemap that looks like this:

%typemap(out) TagLib::String {
        if ($1.isNull()) $result = Qnil;
        else $result = rb_str_new2($1.toCString());
}

I will read the rest of your message and try your suggestions later
tomorrow as it's quite late here and I sure I will mess something else
up if I don't get some sleep.

Thanks again and sorry for the mistake.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Marcelo Matus
The out typemap is ok, but that will never be used in this case,  since
you are not
wrapping a function output value. Also the typemap reveals you are not using
TagLib::String as a pointer object which requires a NewPointerObj, but as
a "primitive value" converted into a ruby string primitive value.

So, you will need to define something like this:

%{
VALUE SWIG_From_TagLibString(const TagLib::String& s) {
     return rb_str_new2(s.toCString());
}
%}

and use the %specialize_mylist macro as follow:

%specialize_mylist(MyList_int, int, SWIG_From(int))
%specialize_mylist(MyList_double, double, SWIG_From(double))
%specialize_mylist(MyList_tgstring, TagLib::String, SWIG_From_TagLibString)


where the %specialize_mylist was defined in the last mail similar to:

%define %specialize_mylist(Name, Type, FromMethod)
%extend MyList<Type> {
void each() {
 MyList::ConstIterator i;
  for (i=self->begin(); i!=self->end(); ++i) {
      VALUE x = FromMethod((Type)(*i));
       rb_yield(x);
  }
}
}
%template(Name) MyList<Type>;
%enddef


marcelo
 
nerochiaro wrote:

>>I see your problem, you are wrapping "primitive" types (int, double, etc).
>>
>>The SWIG_NewPointerObj/SWIG_TypeQuery methods are needed when you
>>wrap 'user types', as classes, not primitive types.
>>    
>>
>
>I have to apologize here. Looking at the code I posted in my previous
>message I noticed that I had pasted one of the two functions wrong.
>That function wrapping an int was just a test that i later removed.
>The true function that causes the problem is the following:
>
>SWIGINTERN void
>TagLib_List_Sl_TagLib_String_Sg__each(TagLib::List<TagLib::String >
>*self){
> static swig_type_info *desc = SWIG_TypeQuery("TagLib::String" " *");
> TagLib::List<TagLib::String>::ConstIterator i;
> for (i=self->begin(); i!=self->end(); ++i)
> {
> VALUE x = SWIG_NewPointerObj((void *) &(*i), desc, 0);
> rb_yield(x);
> }
>}
>
>Which uses a pointer type (TagLib::String), for which I already
>defined a typemap that looks like this:
>
>%typemap(out) TagLib::String {
> if ($1.isNull()) $result = Qnil;
> else $result = rb_str_new2($1.toCString());
>}
>
>I will read the rest of your message and try your suggestions later
>tomorrow as it's quite late here and I sure I will mess something else
>up if I don't get some sleep.
>
>Thanks again and sorry for the mistake.
>
>  
>



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

Charlie Savage
In reply to this post by Marcelo Matus
What is the target date for 1.3.28?

Charlie

Marcelo Matus wrote:

> The problem now is that all the template things around that example,
> and the STD/STL support
> in python, will probably change since I am waiting 1.3.28 to be out to
> start working in unifying
> the STD/STL support, using similar techniques, inside the UTL. Then we
> will have the same
> support/classes we have in the STD/STL for python in all the other
> languages that use the
> UTL, including standard ways to wrap vectors, arrays and so on.
>
> So, if there is time, I will try better to add more docs in the "first
> part" of the UTL, ie
> typemaps and support for simple types, which use the idioms or either
> 'by value' or 'pointer' types.
>
> In the long term the UTL should support
>
> 1.- By value types [done]: as int, double, short, float, etc, which
> can be used as follow:
>
>      int foo(int);
>
> 2.- Pointers types [done], as virtual classes and others types which
> can't (or are not recommended to)
>     be used as simple 'by value' types, and usually are used as:
>
>       MyClass *foo(MyClass *);
>
> 3.- Strings [*done]: generalization of the C strings, or the  'char *'
> type, but considering
>     different kind of characters, as wchar_t, UTF8_t, TCL_UChar *,
> etc. Also known as arrays
>     with a null char terminator.
>
>     * it is someway done in the current STL, but it will be changed to
> accept different kind
>        of Char types in a simpler way.
>
> 3.- C Sequences[not yet]: simple C sequences as 'double vector[100]'
>
> 4.- General C++ sequences[not yet]:  for example  template<class T>
> Vector;
>
> 5.- STL/STD support as general C++ sequences [not yet, but working in
> python]: as std::vector, std::list, etc.
>
>
> Marcelo
>
> Charlie Savage wrote:
>
>> That's clever.
>>
>> Marcelo, any chance you can update the SWIG documentation to show
>> examples of all these tricks?   In fact, I think it would be great to
>> have a significantly update the typemaps section with plenty of
>> examples like these, plus lots of examples of using the new unified
>> typemaps (which I find a bit hard to wrap my mind a round).  In fact,
>> maybe just a full chapter, with examples that use the new typemaps
>> since those would be applicable to multiple languages.  Then we could
>> remove some of the examples from the Ruby/Python/TCL/Perl sections
>> and move them into this new section.  It should be "cookbook" style -
>> thus "If you want to wrap vectors of pointers then do this"
>>
>> Charlie
>>
>> Marcelo Matus wrote:
>>
>>> Well, in theory yes, in the practice no, since $descriptor is only
>>> expanded inside
>>> a typemap, not inside an %extend cdecl.  That makes
>>> SWIG_NewPointerObj to fail,
>>> SWIG_TypeQuery in the other hand, works fine outside a typemap.
>>>
>>> Anyway if a %typemap(out) ELEM * {} is needed, just define it as
>>>
>>> %extend  {
>>>    %typemap(out) ELEM * {...}
>>> }
>>>
>>> you can even define the extend outside the class declaration:
>>>
>>> %extend  MyList {
>>>    %typemap(out) ELEM * {...}
>>> }
>>>
>>> template <class Elem>
>>> class MyList {
>>>   ...
>>> };
>>>
>>> and MyList can even be defined in a separated .h file, as usual.
>>> But, you
>>> need the last swig CVS version.
>>>
>>> Check for example
>>>
>>>   Lib/std/std_carray.swg
>>>   Lib/python/std_carray.i
>>>   Examples/test-suite/python/li_std_carray.i
>>>
>>> for more ideas about mixing %extend + %typemaps + templates.
>>>
>>> This is a small example (that only wok with 1.3.28) that shows several
>>> concepts that will be used in the next STD/STL support for the
>>> UTL(python,perl,tcl,ruby).
>>>
>>> Marcelo
>>>
>>>
>>>
>>>
>>> Charlie Savage wrote:
>>>
>>>> Doesn't the proposed code:
>>>>
>>>> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
>>>> rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>>>>
>>>> Do the same thing as the original?
>>>>
>>>> rb_yield(SWIG_NewPointerObj((void *) &(*i), $descriptor(ELEM *), 0));
>>>>
>>>> Which is get the SWIG descriptor for ELEM* and pass it to the
>>>> SWIG_NewPointerObj method?
>>>>
>>>> I think the question is what if you have a typemap like this:
>>>>
>>>> %typemap(out) ELEM* {
>>>> ....
>>>> }
>>>>
>>>> How can it be applied within the rb_yield in an automated way?  I
>>>> would say that if you have %typemap(out) ELEM* that you define it
>>>> using a fragment, and then call that fragment from your code.  But
>>>> that's not automated, unless you do some fancy macro programming.  
>>>> Maybe there is a better way.
>>>>
>>>> Out of curiosity, which C++ library are you trying to wrap?
>>>>
>>>> Thanks,
>>>>
>>>> Charlie
>>>>
>>>> Marcelo Matus wrote:
>>>>
>>>>> Yes, grab the last cvs version and do
>>>>>
>>>>> %extend  {
>>>>>
>>>>> void each() {
>>>>> static swig_type_info *desc = SWIG_TypeQuery(#ELEM " *");
>>>>> MyList<ELEM>::ConstIterator i;
>>>>> for (i=self->begin(); i!=self->end(); ++i)
>>>>>    rb_yield(SWIG_NewPointerObj((void *) &(*i), desc, 0));
>>>>>  }
>>>>>
>>>>> }
>>>>>
>>>>> nerochiaro wrote:
>>>>>
>>>>>> Hello,
>>>>>> I'm rather new to SWIG and trying to write Ruby bindings for a
>>>>>> C++ library.
>>>>>> I have a std::vector-like template class that I have successfully
>>>>>> wrapped so far.
>>>>>> The only problem comes when I try to extend it to create a function
>>>>>> that implements the typical "each" ruby iterator method. For
>>>>>> non-ruby
>>>>>> programmers, what it does is to iterate across all elements of the
>>>>>> vector and call the ruby API function rb_yield(item) for each one.
>>>>>> The problem lies in the fact that rb_yield expects a ruby object as
>>>>>> input parameter (type VALUE).
>>>>>> The following code works, but has a problem (see below):
>>>>>>
>>>>>> template <class ELEM> class MyList
>>>>>> {
>>>>>> public:
>>>>>>     %extend {
>>>>>>         void each() {
>>>>>>             MyList<ELEM>::ConstIterator i;
>>>>>>             for (i=self->begin(); i!=self->end(); ++i)
>>>>>>                     rb_yield(SWIG_NewPointerObj((void *) &(*i),
>>>>>> $descriptor(ELEM *), 0));
>>>>>>         }
>>>>>>     }
>>>>>> }
>>>>>>
>>>>>> The problem is that if there are typemaps defined for the ELEM type
>>>>>> they won't get applied by SWIG_NewPointerObj.
>>>>>>     I could simply provide a different implementation of each()
>>>>>> for any
>>>>>> specialization that have a typemap defined for, but that gets old
>>>>>> very
>>>>>> fast and kind of misses the point of using templates in the first
>>>>>> place.
>>>>>>
>>>>>> So I was wondering if there was a more elegant (== automated) way
>>>>>> to do it.
>>>>>> What I'm looking for is something that works like SWIG_NewPointerObj
>>>>>> but that also applies typemaps.
>>>>>> Does something like that exist ? If not, can anyone suggest
>>>>>> alternatives ?
>>>>>>
>>>>>> Thanks in advance.
>>>>>>
>>>>>>
>>>>>> -------------------------------------------------------
>>>>>> This SF.net email is sponsored by: Splunk Inc. Do you grep
>>>>>> through log files
>>>>>> for problems?  Stop!  Download the new AJAX search engine that makes
>>>>>> searching your log files as easy as surfing the  web.  DOWNLOAD
>>>>>> SPLUNK!
>>>>>> <a href="http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmdÿk&kid3432&bid#0486&dat1642
>>>>>> _______________________________________________
>>>>>> Swig-user mailing list
>>>>>> [hidden email]
>>>>>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>>>>>
>>>>>>  
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> -------------------------------------------------------
>>>>> This SF.net email is sponsored by: Splunk Inc. Do you grep through
>>>>> log files
>>>>> for problems?  Stop!  Download the new AJAX search engine that makes
>>>>> searching your log files as easy as surfing the  web.  DOWNLOAD
>>>>> SPLUNK!
>>>>> <a href="http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642
>>>>> _______________________________________________
>>>>> Swig-user mailing list
>>>>> [hidden email]
>>>>> https://lists.sourceforge.net/lists/listinfo/swig-user
>>>>>
>>>>>
>>>
>>>
>>>
>
>
>
> -------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc. Do you grep through log
> files
> for problems?  Stop!  Download the new AJAX search engine that makes
> searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
> <a href="http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642
> _______________________________________________
> Swig-user mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/swig-user
>
>

smime.p7s (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Applying typemaps "on demand"

nerochiaro (Bugzilla)
In reply to this post by Marcelo Matus
> The out typemap is ok, but that will never be used in this case,  since
> you are not wrapping a function output value. Also the typemap reveals you
> are not using TagLib::String as a pointer object which requires a NewPointerObj,
> but as a "primitive value" converted into a ruby string primitive value.
>
> So, you will need to define something like this:
>
> %{
> VALUE SWIG_From_TagLibString(const TagLib::String& s) {
>     return rb_str_new2(s.toCString());
> }
> %}
> etc....

I followed your suggestions and I managed to make this work the way I
needed to.
I also have to say that once I understood the logic behind the %define
macros everything was much more easier.
I'm going to experiment a bit more with this feature, looks
interesting and seems to allow for some clever tricks.

Thank you for all the help.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user