4

以下のコードに示すように、クラス内のwrite_data(…)関数からこの関数を呼び出す方法を学習しようとしています。funmain()(これら 2 つの関数をクラス内に配置せずにリストするだけで、このプログラムが機能することはわかっています)。

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data)行でエラーが発生し、 write_data(…) 関数を呼び出せません。私のコードを修正して、これを達成する方法を教えてください。どんな助けでも大歓迎です。ありがとう。

error C3867: 'go_website::write_data': function call missing argument list; use '&go_website::write_data' to create a pointer to member

//Microsoft Visual Studio 10 in C++
#define CURL_STATICLIB
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <iostream>
#include <curl/easy.h>
#include <string>
using namespace std;

extern "C" typedef size_t curl_write_callback(void *ptr, size_t size, size_t nmemb, FILE *stream);
class go_website
{
public:
static curl_write_callback write_data;

void funmain()
{
    CURL *curl;
    FILE *fp;
    CURLcode res;
    char *url = "http://www.shorturl.com/";
    char outfilename[FILENAME_MAX] = "C:\\bbb.txt";
    curl = curl_easy_init();
    if (curl) {
        fp = fopen(outfilename,"wb");
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data); 
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fp);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
        fclose(fp);
    }
}};

extern "C" size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) 
{
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}

int main()
{
   go_website a;
   a.funmain();
   return 0;
}
4

4 に答える 4

10

http://curl.haxx.se/docs/faq.html#Using_C_non_static_functions_f可能です

 // f is the pointer to your object.
 static YourClass::func(void *buffer, size_t sz, size_t n, void *f)
 {
   // Call non-static member function.
   static_cast<YourClass*>(f)->nonStaticFunction();
 }
 // This is how you pass pointer to the static function:
 curl_easy_setopt(hcurl, CURLOPT_WRITEFUNCTION, YourClass:func);
 curl_easy_setopt(hcurl, CURLOPT_WRITEDATA, this);
于 2012-09-06T16:55:15.513 に答える
2

次の 2 行は機能しません。

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fp);

2番目は修正が最も簡単fpです。関数ではなくファイルポインターです。間違った属性を設定していますCURLOPT_WRITEDATA

コールバック関数には、関数ポインターが必要です。通常の関数の名前は、自動的にそのアドレスに減衰しますが、アドレス演算子 ( &functionname) を使用するとよりクリーンになります。

クラス メンバー関数は自動的に減衰しません。実際、非静的クラス メンバ関数は、通常の関数ポインタとは完全に互換性がありません。これは、 を処理する方法がないためthisです。幸いなことに、非静的メンバーはコールバック内で使用されないため、非静的メンバー関数は必要ありません。

コールバック関数を作成static し、extern "C"次のようにします。

extern "C" typedef size_t curl_write_callback(void *ptr, size_t size, size_t nmemb, FILE *stream);

class go_website
{
public:
    static curl_write_callback write_data;

    // ...
};

extern "C" size_t go_website::write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
   size_t written;
   written = fwrite(ptr, size, nmemb, stream);
   return written;
}

次に、アドレス演算子と完全修飾関数名を使用して、そのアドレスを取得します。

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &go_website::write_data);

この部分はエラーメッセージでも説明されていました。staticしかし、 orが必要だとは言いませんでしたextern "C"。これは可変引数リストの問題であり、タイプセーフではありません。

標準 (セクション 7.5 [dcl.link]、特に段落 4 とその例) を読んだ後、これは許可されていません。メンバー関数には、その名前 (重要ではありません) とその型 (これが問題です) の両方について、C++ 言語のリンケージがまだあります。

コールバックにはグローバル関数を使用する必要があります。

extern "C" size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
   size_t written;
   written = fwrite(ptr, size, nmemb, stream);
   return written;
}

次に、それにポインターを渡します。

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data);
于 2012-02-12T05:52:39.240 に答える
1

クラス内に配置せずにこれら2つの関数をリストするだけで、このプログラムが機能することがわかります

クラスの外では機能するが、内部では機能しない場合は、おそらく「this」ポインターを使用する必要があります。

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, this->write_data);
于 2012-02-12T05:47:00.973 に答える
0

問題は、WRITEFUNCTION をクラスのメンバー関数にしたいということです。ただし、curl はそれを呼び出すクラスのインスタンスを認識していません。WRITEFUNCTION に渡す静的関数を作成し、このポインターを CURLOPT_WRITEDATA パラメーターとして渡す必要があります。次に、静的メンバー関数で、user_data ポインター (WRITE_DATA からの「this」) をクラスのインスタンスとして使用できます。

たぶん、この質問が役に立ちます: curl WRITEFUNCTION とクラス

于 2012-02-12T05:55:46.223 に答える