title: How to use libcurl functions inside a Windows Forms Application in Visual C++ 2010?
body: <p>Here is the situation...</p>
  
  <p>I am using Visual C++ 2010 Express.</p>
  
  <p>I am trying to create a windows forms application that can load the source code of any given URL into a RichTextBox.  I wish to accomplish this using the cUrl library.  The good news is, after beating my brains out for more than 24 hours on how to properly link the libcurl.dll file to my project I was successful.  In fact I was able to use the cUrl library to retrieve the source of a url in a Windows console application and print the result to a command window.  So I do not have linking problems.</p>
  
  <p>For reference, below is the source code for the main CPP file for the working test console app:</p>
  
  <pre><code>// MyApplication.cpp : Defines the entry point for the console application.
  //
  
  #include "stdafx.h"
  #include &lt;stdio.h&gt;
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;curl/curl.h&gt;
  
  using namespace std;
  
  int writer(char *data, size_t size, size_t nmemb, string *buffer);
  string curl_httpget(const string &amp;url);
  
  int main(int argc, char *argv[])
  {
      cout &lt;&lt; curl_httpget("http://www.google.com/") &lt;&lt; endl;
  }
  
  string curl_httpget(const string &amp;url)
  {
      string buffer;
  
      CURL *curl;
      CURLcode result;
  
      curl = curl_easy_init();
  
      if (curl)
      {
          curl_easy_setopt(curl, CURLOPT_URL, url.c_str()  );
          curl_easy_setopt(curl, CURLOPT_HEADER, 0);
          curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
          curl_easy_setopt(curl, CURLOPT_WRITEDATA, &amp;buffer);
  
          result = curl_easy_perform(curl);//http get performed
  
          curl_easy_cleanup(curl);//must cleanup
  
          //error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
          if (result == CURLE_OK)
          {
              return buffer;
          }
          //curl_easy_strerror was added in libcurl 7.12.0
          //cerr &lt;&lt; "error: " &lt;&lt; result &lt;&lt; " " &lt;&lt; curl_easy_strerror(result) &lt;&lt;endl;
          return "";
      }
  
      cerr &lt;&lt; "error: could not initalize curl" &lt;&lt; endl;
      return "";
  }
  
  int writer(char *data, size_t size, size_t nmemb, string *buffer)
  {
      int result = 0;
      if (buffer != NULL)
      {
          buffer-&gt;append(data, size * nmemb);
          result = size * nmemb;
      }
      return result;
  }
  </code></pre>
  
  <p>Below is the code for my main project CPP file for my Windows Forms Application "Code Viewer".  The includes work fine here.  I setup all the necessary paths for include and lib, etc.  I am compiling with /CLR (not pure):</p>
  
  <pre><code>// CodeViewer.cpp : main project file.
  
  #include "stdafx.h"
  #include "Form1.h"
  #include &lt;stdio.h&gt;
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;curl/curl.h&gt;
  
  using namespace CodeViewer;
  
  [STAThreadAttribute]
  int main(array&lt;System::String ^&gt; ^args)
  {
      // Enabling Windows XP visual effects before any controls are created
      Application::EnableVisualStyles();
      Application::SetCompatibleTextRenderingDefault(false); 
  
      // Create the main window and run it
      Application::Run(gcnew Form1());
      return 0;
  }
  </code></pre>
  
  <p>Below is the code of my Form1.h for the "Code Viewer" app:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;curl/curl.h&gt;
  
  #pragma once
  
  namespace CodeViewer {
  
      using namespace System;
      using namespace System::ComponentModel;
      using namespace System::Collections;
      using namespace System::Windows::Forms;
      using namespace System::Data;
      using namespace System::Drawing;
      using namespace std;
  
      /// &lt;summary&gt;
      /// Summary for Form1
      /// &lt;/summary&gt;
      public ref class Form1 : public System::Windows::Forms::Form
      {
      public:
          Form1(void)
          {
              InitializeComponent();
              //
              //TODO: Add the constructor code here
              //
          }
  
      protected:
          /// &lt;summary&gt;
          /// Clean up any resources being used.
          /// &lt;/summary&gt;
          ~Form1()
          {
              if (components)
              {
                  delete components;
              }
          }
      private: System::Windows::Forms::RichTextBox^  OutputBox;
      protected: 
      private: System::Windows::Forms::TextBox^  AddressBar;
      private: System::Windows::Forms::Button^  btnGo;
  
      protected: 
  
      private:
          /// &lt;summary&gt;
          /// Required designer variable.
          /// &lt;/summary&gt;
          System::ComponentModel::Container ^components;
  
          //My variables
      private:
          System::String^ iAddress;
          System::String^ iSource;
  
  #pragma region Windows Form Designer generated code
          /// &lt;summary&gt;
          /// Required method for Designer support - do not modify
          /// the contents of this method with the code editor.
          /// &lt;/summary&gt;
          void InitializeComponent(void)
          {
              this-&gt;OutputBox = (gcnew System::Windows::Forms::RichTextBox());
              this-&gt;AddressBar = (gcnew System::Windows::Forms::TextBox());
              this-&gt;btnGo = (gcnew System::Windows::Forms::Button());
              this-&gt;SuspendLayout();
              // 
              // OutputBox
              // 
              this-&gt;OutputBox-&gt;Location = System::Drawing::Point(12, 80);
              this-&gt;OutputBox-&gt;Name = L"OutputBox";
              this-&gt;OutputBox-&gt;Size = System::Drawing::Size(640, 228);
              this-&gt;OutputBox-&gt;TabIndex = 1;
              this-&gt;OutputBox-&gt;Text = L"";
              // 
              // AddressBar
              // 
              this-&gt;AddressBar-&gt;Location = System::Drawing::Point(12, 52);
              this-&gt;AddressBar-&gt;Name = L"AddressBar";
              this-&gt;AddressBar-&gt;Size = System::Drawing::Size(593, 22);
              this-&gt;AddressBar-&gt;TabIndex = 2;
              this-&gt;AddressBar-&gt;TextChanged += gcnew System::EventHandler(this, &amp;Form1::AddressBar_TextChanged);
              // 
              // btnGo
              // 
              this-&gt;btnGo-&gt;Location = System::Drawing::Point(611, 51);
              this-&gt;btnGo-&gt;Name = L"btnGo";
              this-&gt;btnGo-&gt;Size = System::Drawing::Size(41, 23);
              this-&gt;btnGo-&gt;TabIndex = 3;
              this-&gt;btnGo-&gt;Text = L"GO";
              this-&gt;btnGo-&gt;UseVisualStyleBackColor = true;
              this-&gt;btnGo-&gt;Click += gcnew System::EventHandler(this, &amp;Form1::btnGo_Click);
              // 
              // Form1
              // 
              this-&gt;AutoScaleDimensions = System::Drawing::SizeF(8, 16);
              this-&gt;AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
              this-&gt;ClientSize = System::Drawing::Size(664, 320);
              this-&gt;Controls-&gt;Add(this-&gt;btnGo);
              this-&gt;Controls-&gt;Add(this-&gt;AddressBar);
              this-&gt;Controls-&gt;Add(this-&gt;OutputBox);
              this-&gt;Name = L"Form1";
              this-&gt;Text = L"Code Viewer 0.0.0.1";
              this-&gt;Load += gcnew System::EventHandler(this, &amp;Form1::Form1_Load);
              this-&gt;ResumeLayout(false);
              this-&gt;PerformLayout();
  
          }
  #pragma endregion
  
      private: System::Void MarshalString ( System::String^ s, std::string&amp; os )
              {
                  using namespace System::Runtime::InteropServices;
                  const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
                  os = chars;
                  Marshal::FreeHGlobal(IntPtr((void*)chars));
              }
  
      private: System::String^ curl_httpget(const string &amp;url)
              {
                  System::String^ buffer;
  
                  CURL *curl;
                  CURLcode result;
  
                  curl = curl_easy_init();
  
                  if (curl)
                  {
                      curl_easy_setopt(curl, CURLOPT_URL, url.c_str()  );
                      curl_easy_setopt(curl, CURLOPT_HEADER, 0);
                      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
                      curl_easy_setopt(curl, CURLOPT_WRITEDATA, &amp;buffer);
  
                      result = curl_easy_perform(curl);//http get performed
  
                      curl_easy_cleanup(curl);//must cleanup
  
                      //error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
                      if (result == CURLE_OK)
                      {
                          return buffer;
                      }
                      //curl_easy_strerror was added in libcurl 7.12.0
                      //cerr &lt;&lt; "error: " &lt;&lt; result &lt;&lt; " " &lt;&lt; curl_easy_strerror(result) &lt;&lt;endl;
                      return "";
                  }
  
                  cerr &lt;&lt; "error: could not initalize curl" &lt;&lt; endl;
                  return "";
              }
  
      private: int writer(char *data, size_t size, size_t nmemb, string *buffer)
              {
                  int result = 0;
                  if (buffer != NULL)
                  {
                      buffer-&gt;append(data, size * nmemb);
                      result = size * nmemb;
                  }
                  return result;
              }
  
      private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
               }
      private: System::Void btnGo_Click(System::Object^  sender, System::EventArgs^  e) {
                   std::string myAddress = "";
                   MarshalString(iAddress, myAddress);
                   iSource = curl_httpget(myAddress);
                   OutputBox-&gt;Text = iSource;
               }
      private: System::Void AddressBar_TextChanged(System::Object^  sender, System::EventArgs^  e) {
                   iAddress = AddressBar-&gt;Text;
               }
      };
  }
  </code></pre>
  
  <p>I am brand new to C++ and I am just learning how to build Windows Forms Applications so basically I don't know what the heck I'm doing.  I need to be able to call these cUrl functions from inside the Form1.h and I have no idea how to do this.  I want the "GO" button to execute a function call to retrieve the HTML source code of the URL typed into AddressBar using cUrl.  I have probably done in excess of 100 Google searches trying to figure this one out and I am hitting the wall.  I've been searching stackoverflow with the same results.  Always sorta kinda close but not what I'm looking for.  I'm sure there must be a way to do this.</p>
  
  <p>Please be detailed in the response.  I probably won't understand a technical explanation that does not include some sample source code.</p>
  
  <p>Thanks very much in advance!</p>
  
  <hr>
  
  <p>UPDATE: After some more tinkering and tweeking of this code on the advice of Seth (see comments below) I was able to get my code nearly functional.  See the above edited version of Form1.h.  I still have one remaining compiler error, but I think I am close to understanding why I have that error.  Following is that error code:</p>
  
  <pre><code>c:\project\libcurl\visualstudio\codeviewer\codeviewer\Form1.h(137): error C3867: 'CodeViewer::Form1::writer': function call missing argument list; use '&amp;CodeViewer::Form1::writer' to create a pointer to member
  </code></pre>
  
  <p>While my console app had no problem with this code it appears that calling the writer() function without parameters is a problem here.  Right now I'm guessing the solution is to feed it the parameters that it wants, but until I try that I won't know.  It's late so I'm going to bed.  Tomorrow I'll research the parameters needed for the CURLOPT_WRITEFUNCTION...</p>