cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Perl interface 1.1.1

From: Georg Horn <horn_at_koblenz-net.de>
Date: Mon, 16 Apr 2001 14:59:44 +0200

Hi, and happy easter,

On Fri, Apr 13, 2001 at 01:00:59PM +1000, Cris Bailiff wrote:

> I just read your description of 1.1.1 - I'll take a look soon and incorporate
> all the work I've done on callbacks (which I've numbered 1.0.3 at the
> moment). I'm glad you've done the slist cases - that was on my list.
>
> I've got the callbacks working 'just like the C ones' at Forrests request,
> but, as I explained below, its a bit tricky because the callback wrapper
> doesn't know if its being given a FILE * or an SV*. I've made the interface
> continue to work in the default case, where stdio handles are the default
> libcurl handles. Seems to be OK now. I've put some more docco into easy.pm
> and a lot more tests in test.pl. I'm just getting the readfunction stuff
> working better.
>
> I'm not sure you're 'perl internal' options are the best approach for the
> 'return a scalar variable' option. Once we have the callback to perl, we can
> fill a perl variable with a simple perl subroutine.

Thanks to easter, i had some time to study the perlcall manpage and add
callback support to the perl interface. It seems to work quite good, and
it's indeeed only a little bit slower than my internal callback routine
that stores content directly into a buffer. You may download it
from http://koblenz-net.de/~horn/export/Curl-1.1.2.tgz

As always it has no real documentation and only a few (two) test
cases in test.pl. I would be happy if someone would contribute here...

> sub chunk {
> my ($clientp,$data)=@_;
> ${$clientp}.=$data;
> return 0;
> }
>
> $content="";
> Curl::easy::setopy($curl,CURLOPT_FILE,\$content); # ref to variable to be filled
> Curl::easy::setopt($curl,CURLOPT_WRITEFUNCTION, \&chunk); # ref to subroutine
> Curl::easy::perform($curl);
>
> print $content;

Why do you pass a reference to $content into libcurl via CURLOPT_FILE?
You can directly do $content .= $data within your callback...

I just specify a callback via CURLOPT_WRITEFUNCTION and pass all
parameters that come in from libcurl on to the perl callback. The
FILE * that comes in to the write_callback is not yet passed on to
the perl callback, because i found no documentation about converting
a FILE * into a perl filehandle... But i think when using callbacks,
it's not really neccessary to pass on that filehandle, that you have
specified earlier via CURLOPT_FILE. If you can specify it via CURLOPT_FILE,
you must already have that filehandle in your perl programm, and so you can
use it directly in the perl callback function too...

> Subject: Re: Perl interface progress
> Date: Thu, 12 Apr 2001 16:19:18 +1000
> From: Cris Bailiff <c.bailiff_at_awayweb.com>
> To: Forrest Cahoon <forrest.cahoon_at_merrillcorp.com>
> CC: libcurl Mailing list <curl-library_at_lists.sourceforge.net>
> References: <OFDCF32190.C7CD7A5D-ON86256A2B.00519213_at_stp.mrll.com>
>
> Forrest,
>
> > My approach was going to be simpler: instead of putting any smarts in
> > the XS code, I was going to make CURLOPT_FILE just set an SV * which
> > would be passed to a perl write function set with CURLOPT_WRITEFUNCTION,
> > using a simple wrapper like I did for CURLOPT_PROGRESSFUNCTION.
>
> Sorry, but I've been pounding on this one all day now, and it doesn't
> work without breaking the existing 'FILE' function in the interface.
>
> It comes down to the fact that if the perl user sets
> CURLOPT_WRITEFUNCTION, you can't just call pass the SV* to
> curl_easy_setopt(CURLOPT_WRITEFUNCTION,...) because libcurl wants to
> call something with 'frwite' semantics.
>
> So, we need to provide an fwrite-like callback in the XS (as you did for
> the progress function). But this fwrite-replacement needs to know who to
> call back - it gets passed the pointer from CURLOPT_FILE or
> CURLOPT_HEADER to help with this - but what happens if the perl user
> only called CURLOPT_WRITEFUNCTION and not CURLOPT_FILE, or vice versa?

Yes, we need internal callback functions in the XS layer, and some
global SVs where we store references to the perl callbacks. These
references are passed in via CURLOPT_WRITEFUNCTION etc. The
internal callbacks are then registered as a callback to libcurl, and when
they get called they call the perl functions via the global SVs, just
passing on all the parameters they receive from libcurl.
The perlcall manpage has a section about such callback routines...
But why do you want to call both CURLOPT_WRITEFUNCTION and CURLOPT_FILE?
I think it makes only sense to tell libcurl "write data to this filehandle"
or "call this function to write data".

> Any suggestions or comments are welcome - I'm trying to please folk by
> keeping the perl interface exactly like 'C', but it's loosing its perl
> simplicity quite quickly. I really wanted to hide the callback
> complexity if possible...

Well, it's not really complicated. And perls "simplicity" is quite
confusing sometimes... As i'm originally a C programmer, i'd like
to have the perl interface as much like the C interface, if possible...
I don't like functions behaving different if called in different contexts...

Bye,
Georg

_______________________________________________
Curl-library mailing list
Curl-library_at_lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/curl-library
Received on 2001-04-16