libcurl

Übersicht BlitzBasic DLLs und Userlibs

Neue Antwort erstellen

Thunder

Betreff: libcurl

BeitragFr, Nov 13, 2015 1:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo alle miteinander Very Happy

ich glaube das ist mein erster Eintrag hier. Eigentlich tu ich nichts mehr mit BB, aber heute hatte ich irgendwie (nicht ganz zufällig) Lust, ein libcurl Binding zu schreiben.
Also eine kleine feine API für BlitzBasic mit der man mit libcurl Sachen herunterladen kann.

Ich habe es gerade getestet und es _scheint_ zu funktionieren. Verbesserungsvorschläge, Fehlerreports etc sind gerne willkommen, Änderungen und eigene Versionen explizit erlaubt.

Starten wir Mal: Ich verwende das curl_easy_* interface. Leider braucht man da eine Callback-Funktion und BB unterstützt ja keine function pointer. Also habe ich die libcurl 7.45.0 geladen, selber etwas dazu programmiert und sie kompiliert.
Mein hinzugefügter Code ist folgender:
Code: [AUSKLAPPEN]
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <curl/curl.h>

struct Download {

   enum {
      DOWNLOAD_DEST_BUFFER,
      DOWNLOAD_DEST_FILE
   } dst;

   union {
      struct {
         char *buffer;
         size_t buffer_i, buffer_len;
      };
      struct {
         FILE *stream;
         const char *filename;
      };
   };
};

static size_t write_callback(void *buffer, size_t size, size_t nmemb, void *stream)
{
   if(stream == NULL)
      assert(0);

   struct Download *out = (struct Download *)stream;
   
   if (out->dst == DOWNLOAD_DEST_FILE){
      if(out->stream == NULL) {
         out->stream = fopen(out->filename, "wb");
         if (out->stream == NULL)
            return 0;
      }
      return fwrite(buffer, size, nmemb, out->stream);
   }else if(out->dst == DOWNLOAD_DEST_BUFFER){
      if(out->buffer == NULL){
         out->buffer_len = 4096;
         out->buffer = malloc(out->buffer_len);
         out->buffer_i = 0;
      }
      const size_t nlen = size*nmemb;
      if (nlen + out->buffer_i > out->buffer_len) {
         const size_t plus = nlen + 4096;
         char *nb = realloc(out->buffer, out->buffer_len + plus);
         if(nb == NULL)
            return 0;
         out->buffer = nb;
         out->buffer_len += plus;
      }
      memcpy(out->buffer+out->buffer_i, buffer, nlen);
      out->buffer_i += nlen;
      return nmemb;
   }else {
      assert(0);
   }
   
}

__declspec(dllexport) int curl_easy_download_file(CURL *handle, const char *url, const char *filename)
{
   struct Download dl = {
      .dst = DOWNLOAD_DEST_FILE,
      .filename = filename,
      .stream = NULL
   };
   curl_easy_setopt(handle, CURLOPT_URL, url);
   curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
   curl_easy_setopt(handle, CURLOPT_WRITEDATA, &dl);
   const int status = curl_easy_perform(handle) == 0 ? 1 : 0;
   fclose(dl.stream);

   return status;
}

__declspec(dllexport) int curl_easy_download_bank(CURL *handle, const char *url, void **dlptr)
{
   struct Download dl = {
      .dst = DOWNLOAD_DEST_BUFFER,
      .buffer = NULL,
   };
   curl_easy_setopt(handle, CURLOPT_URL, url);
   curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
   curl_easy_setopt(handle, CURLOPT_WRITEDATA, &dl);
   const int status = curl_easy_perform(handle) == 0 ? 1 : 0;
   
   *dlptr = malloc(sizeof(dl));
   if(*dlptr == NULL)
      return 0;
   memcpy(*dlptr, &dl, sizeof(dl));

   return status;
}

__declspec(dllexport) int32_t curl_easy_bank_size(struct Download *dlptr)
{
   return dlptr->buffer_i;
}

__declspec(dllexport) void curl_easy_move_bank(struct Download *dlptr, char *newbank)
{
   memcpy(newbank, dlptr->buffer, dlptr->buffer_i);
   free(dlptr->buffer);
   free(dlptr);
}


Decls:
Code: [AUSKLAPPEN]
.lib "libcurl.dll"

curl_easy_init%():"curl_easy_init"
curl_easy_cleanup(handle%):"curl_easy_cleanup"
curl_easy_download_file%(handle%, url$, filename$):"curl_easy_download_file"
curl_easy_download_bank%(handle%, url$, tmpbank*):"curl_easy_download_bank"
curl_easy_bank_size%(dlhandle%):"curl_easy_bank_size"
curl_easy_move_bank%(dlhandle%, bank*):"curl_easy_move_bank"


Und noch eine freundliche API als BlitzBasic-Funktionen:
BlitzBasic: [AUSKLAPPEN]

Type CurlHandle
Field hd
End Type

Function CurlSetup%()
hd = curl_easy_init()
If hd <> 0 Then
a.CurlHandle = New CurlHandle
a\hd = hd
End If
Return hd
End Function

Function CurlDownload%(hd%, url$, filename$)
Return curl_easy_download_file(hd, url, filename)
End Function

Function CurlDownloadBank%(hd%, url$)
tmp% = CreateBank(4)
status% = curl_easy_download_bank(hd, url, tmp)
If status = 0 Then FreeBank tmp:Return 0

dl% = PeekInt(tmp, 0)
FreeBank tmp

size% = curl_easy_bank_size(dl)
newbank% = CreateBank(size)
curl_easy_move_bank(dl, newbank)

Return newbank
End Function

Function CurlCleanup%(hd% = 0)
cleaned% = 0

If hd = 0 Then
For a.CurlHandle = Each CurlHandle
curl_easy_cleanup a\hd
Next
Delete Each CurlHandle
cleaned = 1
Else
For a.CurlHandle = Each CurlHandle
If a\hd = hd Then
curl_easy_cleanup a\hd
Delete a
cleaned = 1
Exit
EndIf
Next
End If

Return cleaned
End Function



Beispiel:
BlitzBasic: [AUSKLAPPEN]
LINK$ = "http://curl.haxx.se/libcurl/c/curl_easy_perform.html"

; Curl handle initialisieren
; muss nur einmal fürs ganze Programm gemacht werden
; danach muss dieser Handle immer an die Download Funktionen übergeben werden
Global curl = CurlSetup()

; Den LINK als Datei downloaden
CurlDownload curl, LINK, "C:/BlitzPlus/curl_easy_perform.html"

; Den LINK in eine Bank downloaden
Local bank% = CurlDownloadBank(curl, LINK)
For i% = 0 To BankSize(bank)-1
Write Chr(PeekByte(bank,i))
Next
FreeBank bank

; Am Ende des Programms oder wenn man aufhört, curl zu benutzen
; CurlCleanup aufrufen
CurlCleanup curl
curl = 0


Habe euch die DLL hier hochgeladen: https://www.blitzforum.de/upload/file.php?id=13083
Ihr könnt sie mit den Änderungen von mir auch selber bauen, wenn euch das lieber ist.
Eine Standard-libcurl DLL kann man aber leider nicht verwenden.

Viel Spaß beim Probieren

Edit: Meine Änderungen sind public domain (damit das klar ist).
OpenSource FTW! aber seid gewarnt: OS-Projekte als GPL zu lizenzieren ist eine Sünde
Meine Sachen: https://github.com/chtisgit

Neue Antwort erstellen


Übersicht BlitzBasic DLLs und Userlibs

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group