C++来自 C API 的类成员函数和回调

发布于 2025-01-05 02:22:04 字数 1607 浏览 0 评论 0原文

我正在尝试学习如何从类中的 funmain() 函数调用此 write_data(…) 函数,如下面的代码所示。 (我知道如果我只列出这两个函数而不将其放入类中,该程序就可以工作)。

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;
}

I am trying to learn how to call this write_data(…) function from the funmain() function in the class as shown in the code bellow. (I know this program works if I just list these two functions without putting it inside a class).

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data) line gives me error and wouldn’t let me call the write_data(…) function. Can you please correct my code and tell me how I can achieve this. Any help would be greatly appreciated. Thanks.

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

绝對不後悔。 2025-01-12 02:22:04

有可能 http://curl.haxx.se/docs/faq.html#Using_C_non_static_functions_f< /a>

 // 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);

It is possible 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);
墨离汐 2025-01-12 02:22:04

这两行不起作用:

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

第二行是最容易修复的: 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);

这部分甚至在错误消息中进行了解释。但它没有告诉您需要 staticextern "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);

These two lines won't work:

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

The second is the easiest to fix: fp is a file pointer, not a function, you're setting the wrong attribute, I guess you want CURLOPT_WRITEDATA.

For the callback function, you need a function pointer. The name of an ordinary function automatically decays to its address, although using the address-of operator (&functionname) is cleaner.

Class member functions do not automatically decay. In fact, a non-static class member function is totally incompatible with a normal function pointer, since there's no way to handle this. Luckily you don't need a non-static member function, since no non-static members are used inside the callback.


Make the callback function static andextern "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;
}

and then take its address, using the address-of operator and fully-qualified function name:

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

This part was even explained in the error message. But it didn't tell you that you needed static or extern "C", this is the problem with variable argument lists, they aren't typesafe.

After reading the Standard (section 7.5 [dcl.link], and especially paragraph 4 and its examples), this isn't allowed. The member function still has C++ language linkage, for both its name (not important) and its type (this is the deal-breaker).

You have to use a global function for the callback:

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;
}

and then pass a pointer to it:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data);
古镇旧梦 2025-01-12 02:22:04

如果我只列出这两个函数而不将其放入

如果它在类外部工作,但不在类内部工作,那么您可能需要使用“this”指针。

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, this->write_data);

I know this program works if I just list these two functions without putting it inside a
class

If it works outside of a class, but not inside, then you likely need to use the "this" pointer.

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, this->write_data);
紫罗兰の梦幻 2025-01-12 02:22:04

问题是您希望 WRITEFUNCTION 成为您的类的成员函数。但是,curl 不知道要调用该类的哪个实例。您需要创建一个传递给 WRITEFUNCTION 的静态函数,然后将 this 指针作为 CURLOPT_WRITEDATA 参数传递。然后在静态成员函数中,您可以使用 user_data 指针(即 WRITE_DATA 中的“this”)作为类的实例。

也许这个问题会有所帮助: curl WRITEFUNCTION 和类

The problem is that you want the WRITEFUNCTION to be a member function of your class. However, curl doesn't know which instance of the class to call it on. You need to create a static function that you pass to WRITEFUNCTION and then pass your this pointer as the CURLOPT_WRITEDATA parameter. Then in your static member function you can use the user_data pointer (which is your "this" from WRITE_DATA) as the instance of the class.

Maybe this question will help: curl WRITEFUNCTION and classes

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文