libcurl的标准字符串问题 - c ++

时间:2010-03-07 05:30:08

标签: c++ string visual-studio-2005 libcurl

我对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)。

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

我认为您只需要小心将调试版本与libcurl的调试版本链接,并使用发行版本构建版本。否则你的程序的一部分需要msvcrt.lib而部分需要msvcrtd.lib,如果你试图同时使用它们就会发生冲突。

编辑回应提问者的评论:

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

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

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

答案 2 :(得分: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;
}  

此解决方案非常适合我,并将信息存储在 chunk.memory 成员中。 告诉我它是否对你有用!