2010-11-19 6 views
2

Ich versuche, diese Curl-Funktion in meine Klasse aufzunehmen, aber Probleme mit CURLOPT_WRITEFUNCTION. Nach der Zusammenstellung habe ich keine Lösung gefunden. Habe auch einige Sachen versucht, die auf stackoverflow zu keinem verfügbar sind.CURLOPT_WRITEFUNCTION Zeiger auf Member-Funktion

Hier ist mein Versuch (als Ersatz für 'Schreiber' in diesem Code)

Knoten :: Schreiber & Knoten :: Schriftsteller std :: bind1st (std :: mem_fun (& Knoten :: writer), this) ;

mein Code hier:

#ifndef NODE_H_ 
#define NODE_H_ 

int writer(char *data, std::size_t size, std::size_t nmemb, std::string *buffer); 

/* 
* function prototypes 
*/ 

class node { 
/* 
    * general struct to hold html element properties 
    */ 
struct tag; 

/* 
    * the url and source of the page 
    */ 
std::string url; 
std::string source; 

/* 
    * vector of structures that store tag elements 
    */ 
std::vector<tag> heading; 
std::vector<tag> anchor; 

/* 
    * grab source with curl 
    */ 
std::string curlHttpget(const std::string &url); 

/* 
    * add tag structs to vector 
    * @see std::vector<tag> heading 
    * @see std::vector<tag> anchor 
    */ 
void add_heading(std::string, std::string); 
void add_anchor(std::string, std::string); 

public: 
/* 
    * constructors 
    */ 
node(){} 
node(std::string); 

/* 
    * deconstructors 
    */ 
~node(){} 

/* 
    * crawl page 
    */ 
void load(std::string seed);//crawls the page 

/* 
    * anchor tags 
    */ 
void get_anchors();// scrape the anchor tags 
void display_anchors(); 

/* 
    * heading tags 
    */ 
void get_headings();// scrape heading tags 
void display_headings(); 
}; 
/* 
* for all stored html elements 
*/ 
struct node::tag { 
std::string text; 
std::string properties; 
tag(std::string t, std::string p) : text(t), properties(p) {} 
}; 

/* 
* constructors 
*/ 
node::node(std::string seed) { 
load(seed); 
get_anchors(); 
get_headings(); 
} 
/* 
* araneus::subroutines 
*/ 

// crawl the page 
void node::load(std::string seed) { 
url = seed; 
source = curlHttpget(url); 
} 


//scrape html source 
std::string node::curlHttpget(const std::string &url) { 
std::string buffer; 

CURL *curl; 
CURLcode result; 

curl = curl_easy_init(); 

if (curl) { 
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); 
    curl_easy_setopt(curl, CURLOPT_HEADER, 0); 
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer); 
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); 

    result = curl_easy_perform(curl);//http get performed 

    curl_easy_cleanup(curl);//must cleanup 

    //error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html 
    if (result == CURLE_OK) { 
    return buffer; 
    } 
    //curl_easy_strerror was added in libcurl 7.12.0 
    std::cerr << "error: " << result << " " << curl_easy_strerror(result) << std::endl; 
    return ""; 
} 

std::cerr << "error: could not initalize curl" << std::endl; 
return ""; 
} 

void node::get_headings() { 
static const regex expression("<[hH][1-6]\\s*(?<properties>.*?)\\s*>(?<name>.*?)</\\s*[hH][1-6]\\s*>"); 

int const subMatches[] = { 1, 2 }; 

sregex_token_iterator p(source.begin(), source.end(), expression, subMatches); 
sregex_token_iterator end; 

string text; 
string properties; 

int count = 0; 
for (;p != end; count++, ++p) 
{ 
    string m(p->first, p->second); 

    if(count % 2) { 
    text = m; 
    add_heading(text, properties); 
    } 
    else { 
    properties = m; 
    } 
} 
} 

//use regex to find anchors in source 
void node::get_anchors() { 
static const regex expression("<[a|A].*?[href|HREF]\\s*=[\"\"'](?<url>.*?)[\"\"'].*?>(?<name>.*?)</[a|A]>"); 
static const regex relative("^\\/"); 
static const regex firstChar("^[A-Za-z0-9\\-_\\$\\.\\+!\\*'\\(\\)#]"); // valid url characters 
static const regex protocol("^[http:\\/\\/|HTTP:\\/\\/|https:\\/\\/|HTTPS:\\/\\/|ftp:\\/\\/|FTP:\\/\\/|sftp:\\/\\/|SFTP:\\/\\/]"); 

int const subMatches[] = { 1, 2 }; 

sregex_token_iterator p(source.begin(), source.end(), expression, subMatches); 
sregex_token_iterator end; 

string text, properties; 

int count = 0; 
for (; p != end; count++, ++p) { 
    std::string m(p->first, p->second); 

    if(count % 2) { 
    text = m; 
    add_anchor(text, properties); 
    } 
    else { 
    if(regex_search(m, relative)) { //if link is in "/somewhere" format 
    properties = url + m; 
    } 
    else if(regex_search(m, protocol)) { //if link is absolute "http://www.somewhere.com" 
    properties = m; 
    } 
    else if(regex_search(m, firstChar)) { //if link starts with a valid url char "somewhere.html" 
    properties = url + "/" + m; 
    } 
    else { 
    std::cout << "link of unknown protocol: " << m << std::endl; 
    } 
    } 
} 
} 

void node::add_heading(std::string text, std::string properties) { 
heading.push_back(tag(text, properties)); 
} 

void node::display_headings() { 
for(int i = 0; i < (int)heading.size(); i++) { 
    std::cout<< "[h]: " << heading[i].text << endl; 
    std::cout<< "[h.properties]: " << heading[i].properties << endl; 
} 
cout << "found " << (int)heading.size() << " <h[1-6]> tags" << endl; 
} 

void node::add_anchor(std::string text, std::string properties) { 
anchor.push_back(tag(text, properties)); 
} 

void node::display_anchors() { 
for(int i = 0; i < (int)anchor.size(); i++) { 
    std::cout<< "[a]: " << anchor[i].text << endl; 
    std::cout<< "[a.properties]: " << anchor[i].properties << endl; 
} 
cout << "found " << (int)anchor.size() << " <a> tags" << endl; 
} 

//required by libcurl 
int writer(char *data, std::size_t size, std::size_t nmemb, std::string *buffer) { 
int result = 0; 

if (buffer != NULL) { 
    buffer->append(data, size * nmemb); 
    result = size * nmemb; 
} 
return result; 
} 

#endif /* NODE_H_ */ 

nach einer Lösung suchen, um die Funktion 'int writer' zu bekommen "int Knoten :: writer" zu sein. Das Problem tritt in std :: string node :: curlHttpget auf, wenn ich CURLOPT_WRITEFUNCTION aufruft.

& Knoten :: Schriftsteller kompiliert, sondern gibt einen seg Fehler =/

dank

Antwort

1

Statt std :: string * Verwendung Knoten * als Parameter oder eine andere Klasse wie HttpGet zu verwenden, die eine std hat: : Zeichenkette und ein Zeiger zurück zu Ihrem Knoten, damit er in die Zeichenkette schreiben und bei jedem Aufruf auf Ihren Knoten zugreifen kann.

boost :: bind funktioniert nicht für C-API Callbacks.

Es kompiliert, weil curl_easy_setopt verwendet ... also ist absolut nicht typsicher. Sie können es jedem beliebigen Typ unter die Sonne geben und es wird kompiliert. Es wird wahrscheinlich nicht laufen, wie Sie zu Ihren Kosten gefunden haben.

Ich würde für die zusätzliche Typ-Sicherheit, um Ihre Funktion genau die gleiche Signatur wie Curl_write_callback haben, d. H. Void * als 4. Parameter, und das Casting in der Funktion Implementierung gehen.

Verwandte Themen