std string problem with libcurl - c++
I'm pretty new to c++ and I'm using libcurl to make an http request and 开发者_高级运维get back a string with the respond's content.
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;
}
after running the above code (with VS2005) I get this errors:
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)
its seems like its a problem with some libraries and I tried adding "msvcrtd.lib" and I still get the error above with additional new errors.
Answer: I changed the Run Time Library from Multi-Threaded (/MT) to Multi-threaded Debug DLL (/MDd).
You would need to download and compile the source code to get your DLLs/Library files. I had the similar debugging and linking problems with binary version I downloaded for VS 2005. Make sure you include the header and library paths in compiler options and to link the libcurl.dll etc. just put it in the working directory or system32 folder.
std::string generally should not be part of a public interface of a library distributed in binary form (object, static lib, or DLL). But libcurl is pretty intelligently designed, probably the std::string support is provided by an include file (that's ok) which converts things to a portable format before calling into the library.
I think you just need to be careful to link your debug builds with the debug version of libcurl, and your release builds with the release version. Otherwise part of your program wants msvcrt.lib and part wants msvcrtd.lib, and they conflict if you try to use both at once.
EDIT in response to the asker's comment:
There's a dropdown combo box in the compile/build toolbar, that lets you select between Debug and Release configurations.
Also, the Linker "Additional Inputs" setting in the project properties can have different values for Debug and Release. Probably the debug version should use "libcurld.lib" and the release version "libcurl.lib", but not everyone follows that same convention.
If you added the .lib file to your project instead of listing it in the link options, you can still do this by adding both variants and setting "Exclude this file from the build" appropriately. But this looks ugly and will confuse anyone else who works on the project. I would use the Linker options in the project properties.
//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();
}
here is the code that you need to make the request... as you could see, you must create a static method called WriteMemoryCallback which is coded like this:
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!
精彩评论