0

我对 c++ 很陌生,我正在使用 libcurl 发出一个 http 请求并返回一个包含响应内容的字符串。

size_t write_to_string(void *ptr, size_t size, size_t count, void *stream) {
    ((std::string*)stream)->append((char*)ptr, 0, size*count);
    return size*count;
}

int main(void) {

    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();

  if (curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.browsarity.com/");

    std::string response;
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_string);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);

    // The "response" variable should now contain the contents of the HTTP response
  }
  return 0;
}

运行上述代码(使用 VS2005)后,出现以下错误:

1>libcpmtd.lib(xdebug.obj) : error LNK2019: unresolved external symbol __malloc_dbg referenced in function "void * __cdecl operator new(unsigned int,struct std::_DebugHeapTag_t const &,char *,int)" (??2@YAPAXIABU_DebugHeapTag_t@std@@PADH@Z)
1>libcpmtd.lib(xdebug.obj) : error LNK2019: unresolved external symbol __free_dbg referenced in function "void __cdecl operator delete(void *,struct std::_DebugHeapTag_t const &,char *,int)" (??3@YAXPAXABU_DebugHeapTag_t@std@@PADH@Z)
1>libcpmtd.lib(stdthrow.obj) : error LNK2019: unresolved external symbol __CrtDbgReportW referenced in function "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z)

它似乎是某些库的问题,我尝试添加“msvcrtd.lib”,但我仍然收到上面的错误以及其他新错误。

答:我将运行时库从多线程 (/MT) 更改为多线程调试 DLL (/MDd)。

4

3 回答 3

1

您需要下载并编译源代码以获取您的 DLL/库文件。我为 VS 2005 下载的二进制版本遇到了类似的调试和链接问题。确保在编译器选项中包含头文件和库路径,并链接 libcurl.dll 等,只需将其放在工作目录或 system32 文件夹中即可。

于 2010-03-07T05:54:16.843 回答
0

std::string 通常不应成为以二进制形式(对象、静态库或 DLL)分发的库的公共接口的一部分。但是 libcurl 的设计非常智能,可能 std::string 支持是由一个包含文件(没关系)提供的,它在调用库之前将内容转换为可移植格式。

我认为您只需要小心将调试版本与 libcurl 的调试版本链接,并且您的发布版本与发布版本相关联。否则,您的程序的一部分需要 msvcrt.lib,一部分需要 msvcrtd.lib,如果您尝试同时使用两者,它们会发生冲突。

编辑以回应提问者的评论:

编译/构建工具栏中有一个下拉组合框,可让您在调试和发布配置之间进行选择。

此外,项目属性中的链接器“附加输入”设置可以具有不同的调试和发布值。可能调试版本应该使用“libcurld.lib”和发布版本“libcurl.lib”,但不是每个人都遵循相同的约定。

如果您将 .lib 文件添加到您的项目中,而不是在链接选项中列出它,您仍然可以通过添加两个变体并适当地设置“从构建中排除此文件”来执行此操作。但这看起来很丑陋,并且会使从事该项目的其他任何人感到困惑。我会在项目属性中使用链接器选项。

于 2010-03-07T05:34:49.137 回答
0
    //login
    curl_easy_setopt(handle,CURLOPT_USERNAME,username);
    curl_easy_setopt(handle,CURLOPT_PASSWORD,password);

    m_popsAccount = "pop3s://pop.gmail.com:995/"; //this URL only returns the list of emails with "[index] [size]" format

    curl_easy_setopt(handle, CURLOPT_URL, m_popsAccount.c_str());
    curl_easy_setopt(handle, CURLOPT_USE_SSL, CURLUSESSL_ALL); 
    curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); 
    curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0); 

    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); 

    curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)&chunk);
    //some servers needs this validation
    curl_easy_setopt(handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    res = curl_easy_perform(handle); 

    if(res != CURLE_OK)
    {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
            curl_easy_strerror(res));
    }
    else 
    {
        printf("%s\n",chunk.memory); //here is the information
    }

    if(chunk.memory)
        free(chunk.memory);
    /* always cleanup */ 

    curl_global_cleanup();
}

这是您发出请求所需的代码...如您所见,您必须创建一个名为 WriteMemoryCallback 的静态方法,其编码如下:

struct MemoryStruct {
    char *memory;
    size_t size;
};  

size_t MailServer::WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
    if(mem->memory == NULL)
    {
        /* out of memory! */ 
        printf("not enough memory (realloc returned NULL)\n");
        return 0;
    }

    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;

    return realsize;
}  

This solution works perfectly for me, and stores the info inside chunk.memory member. Tell me if it was useful for you!

于 2013-11-08T13:20:59.623 回答