C ++类成员函数和来自C API的回调 [英] C++ class member function and callback from C API

查看:281
本文介绍了C ++类成员函数和来自C API的回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从 funmain()函数中学习如何调用 write_data(...)类如下面代码所示。 (我知道这个程序工作,如果我只是列出这两个函数,而不把它放在类中)。

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)行给我错误,不会让我调用write_data ...)。你能更正我的代码,告诉我如何实现这一点。任何帮助将非常感谢。谢谢。

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


推荐答案

工作:

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

第二个是最容易修复的: fp 是一个文件指针,而不是一个函数,你正在设置错误的属性,我想你想要 CURLOPT_WRITEDATA

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.

对于回调函数,需要一个函数指针。尽管使用运算符(& functionname )的地址更干净,但普通函数的名称自动衰减到其地址。

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.

类成员函数不会自动衰减。事实上,非静态类成员函数与普通函数指针完全不兼容,因为没有办法处理 this 。幸运的是,你不需要非静态成员函数,因为在回调中没有使用非静态成员。

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.


回调函数 static externC

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

这部分甚至在错误消息中解释。但它没有告诉你你需要 static externC,这是可变参数的问题列表,它们不是类型安全的。

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.

阅读标准之后(第7.5节 [dcl.link] 特别是第4段及其例子),这是不允许的。成员函数仍然有C ++语言链接,对它的名字(不重要)和它的类型(这是交易断路器)。

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).

你必须使用全局函数:

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

这篇关于C ++类成员函数和来自C API的回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆