Libcurl and downloading web file.

BlitzMax Forums/Brucey's Modules/Libcurl and downloading web file.

Rixarn(Posted 2010) [#1]
Hi brucey!

I'm making a very simple updater for my program using libcurl.

Can you give me some advice in how to use the WriteFunction?

Basically, what I have is something like this:



data:Object is allways null and i dont know how can i use it if it's just a local object for that function.

I know i could just declare a global object that references a stream and write the byte buffers to that stream inside the writeFunction, but that doesn't looks like an elegan solution. he he... What i want to do is download files greater than 1mb, and have the means via Libcurl to detect if internect connection was lost.

Btw.. how can you pass a function as an argument for a method/function? is that documented somewhere? Seems like a very interesting feature... I was surprised i could do this:

curl.setWriteCallback(writeFunction)


but not this

local buff:byte ptr
local size:int
local data:object
curl.setWriteCallback(writeFunction(buff,size,data))


Thanks in advance!


Brucey(Posted 2010) [#2]
There are several ways you might want to handle writing.

setWriteCallback() takes two parameters: a function pointer and optional user/context object. The user object is something that is passed back to you on each call to your callback function. You might use the object to store the data as it is downloaded, or it might write the data out to a file.
Passing this object into the function means that it doesn't need to be global. Libcurl will reference it until the download is finished.

There is also a setWriteStream() method, which takes a TStream as a parameter. This should be a stream that is writable - i.e. it's write() method will be called.
There's an example of a custom stream in the ex_03.bmx example that comes with the module. Of course, you don't really need to make up a custom stream. It could simply be a file stream opened with WriteStream().
(Remember to close your writable stream when finished!)

Handling half-complete downloads is more tricky though. You can do this perhaps by checking to see if you have a file with the same name, and comparing its size to the size of the file on the web server. If it was a partial download you could even open the file for appending, and fetch the rest of the data from a given resume point (assuming the server supports it).
But that's all quite complex, and some of the things I've mentioned are not directly supported in BlitzMax (like appendable streams - although I posted an example implementation of one here a while ago).

As for function pointers, they are very useful, especially for callbacks.
A function is defined to accept a parameter which is itself a function of a given signature.
This is useful because it allows you to potentially override a function with your own. A function pointer can be defined like any normal function, including a return type if required.

Here's a small example, which shows how one might use it to override some default functionality :
SuperStrict

Framework BRL.StandardIO

Type TCallbackTest

	Field userCallback(text:String)

	Method setCallback(callback(text:String))
		userCallback = callback
	End Method

	Method call(text:String)
		If userCallback Then
			userCallback(text)
		Else
			defaultImplementation(text)
		End If
	End Method

	Function defaultImplementation(text:String)
		Print "defaultImplementation : " + text
	End Function

End Type

Function myCallback(text:String)
	Print "myCallback : " + text
End Function


Local cbTest:TCallbackTest = New TCallbackTest

' use the default implementation
cbTest.call("Hello!")

' override
cbTest.setCallback(myCallback)

' use the custom callback
cbTest.call("BlitzMax rocks!")


:o)


Rixarn(Posted 2010) [#3]
Thank you very much Brucey! Now i can get to work :) And thanks also for the function pointer example, i'll be sure to learn it :)!