Вот ситуация ...
Я использую Visual C ++ 2010 Express.
Я пытаюсь создать приложение для форм Windows, которое может загрузить исходный код любого заданного URL-адреса в RichTextBox. Я хочу сделать это с помощью библиотеки cUrl. Хорошей новостью является то, что после более чем 24-часового перерыва в работе над тем, как правильно связать файл libcurl.dll с моим проектом, я добился успеха. Фактически я смог использовать библиотеку cUrl, чтобы получить источник URL-адреса в консольном приложении Windows и распечатать результат в командном окне. Так что у меня нет проблем со связыванием.
Для справки ниже приведен исходный код основного файла CPP для рабочего приложения консоли тестирования:
// MyApplication.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <curl/curl.h>
using namespace std;
int writer(char *data, size_t size, size_t nmemb, string *buffer);
string curl_httpget(const string &url);
int main(int argc, char *argv[])
{
cout << curl_httpget("http://www.google.com/") << endl;
}
string curl_httpget(const string &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, &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 << "error: " << result << " " << curl_easy_strerror(result) <<endl;
return "";
}
cerr << "error: could not initalize curl" << endl;
return "";
}
int writer(char *data, size_t size, size_t nmemb, string *buffer)
{
int result = 0;
if (buffer != NULL)
{
buffer->append(data, size * nmemb);
result = size * nmemb;
}
return result;
}
Ниже приведен код моего CPP-файла основного проекта для моего приложения Windows Forms «Просмотр кода». Включает отлично работать здесь. Я устанавливаю все необходимые пути для include, lib и т. Д. Я компилирую с / CLR (не чисто):
// CodeViewer.cpp : main project file.
#include "stdafx.h"
#include "Form1.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <curl/curl.h>
using namespace CodeViewer;
[STAThreadAttribute]
int main(array<System::String ^> ^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;
}
Ниже приведен код моего Form1.h для приложения «Просмотр кода»:
#include <stdio.h>
#include <iostream>
#include <string>
#include <curl/curl.h>
#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;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~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:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
//My variables
private:
System::String^ iAddress;
System::String^ iSource;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->OutputBox = (gcnew System::Windows::Forms::RichTextBox());
this->AddressBar = (gcnew System::Windows::Forms::TextBox());
this->btnGo = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// OutputBox
//
this->OutputBox->Location = System::Drawing::Point(12, 80);
this->OutputBox->Name = L"OutputBox";
this->OutputBox->Size = System::Drawing::Size(640, 228);
this->OutputBox->TabIndex = 1;
this->OutputBox->Text = L"";
//
// AddressBar
//
this->AddressBar->Location = System::Drawing::Point(12, 52);
this->AddressBar->Name = L"AddressBar";
this->AddressBar->Size = System::Drawing::Size(593, 22);
this->AddressBar->TabIndex = 2;
this->AddressBar->TextChanged += gcnew System::EventHandler(this, &Form1::AddressBar_TextChanged);
//
// btnGo
//
this->btnGo->Location = System::Drawing::Point(611, 51);
this->btnGo->Name = L"btnGo";
this->btnGo->Size = System::Drawing::Size(41, 23);
this->btnGo->TabIndex = 3;
this->btnGo->Text = L"GO";
this->btnGo->UseVisualStyleBackColor = true;
this->btnGo->Click += gcnew System::EventHandler(this, &Form1::btnGo_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(8, 16);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(664, 320);
this->Controls->Add(this->btnGo);
this->Controls->Add(this->AddressBar);
this->Controls->Add(this->OutputBox);
this->Name = L"Form1";
this->Text = L"Code Viewer 0.0.0.1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void MarshalString ( System::String^ s, std::string& 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 &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, &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 << "error: " << result << " " << curl_easy_strerror(result) <<endl;
return "";
}
cerr << "error: could not initalize curl" << endl;
return "";
}
private: int writer(char *data, size_t size, size_t nmemb, string *buffer)
{
int result = 0;
if (buffer != NULL)
{
buffer->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->Text = iSource;
}
private: System::Void AddressBar_TextChanged(System::Object^ sender, System::EventArgs^ e) {
iAddress = AddressBar->Text;
}
};
}
Я новичок в C ++, и я только учусь создавать приложения Windows Forms, так что в основном я не знаю, какого черта я делаю. Мне нужно иметь возможность вызывать эти функции cUrl из Form1.h, и я понятия не имею, как это сделать. Я хочу, чтобы кнопка «GO» выполнила вызов функции, чтобы получить исходный HTML-код URL-адреса, введенного в AddressBar с помощью cUrl. Я, вероятно, сделал более 100 поисков в Google, пытаясь выяснить это, и я бью стену. Я искал stackoverflow с теми же результатами. Всегда вроде как близко, но не то, что я ищу. Я уверен, что должен быть способ сделать это.
Пожалуйста, уточните в ответе. Я, вероятно, не пойму техническое объяснение, которое не включает некоторый пример исходного кода.
Заранее большое спасибо!
ОБНОВЛЕНИЕ: После еще нескольких изменений и настройки этого кода по совету Сета (см. Комментарии ниже) я смог сделать мой код почти функциональным. Смотрите выше отредактированную версию Form1.h. У меня все еще остается одна ошибка компилятора, но я думаю, что я близок к пониманию, почему у меня эта ошибка. Ниже приведен код ошибки:
c:\project\libcurl\visualstudio\codeviewer\codeviewer\Form1.h(137): error C3867: 'CodeViewer::Form1::writer': function call missing argument list; use '&CodeViewer::Form1::writer' to create a pointer to member
Хотя мое консольное приложение не имело проблем с этим кодом, похоже, что вызов функции writer () без параметров является проблемой здесь. Прямо сейчас я предполагаю, что решение состоит в том, чтобы передать ему параметры, которые он хочет, но пока я не попробую, я не буду знать. Уже поздно, поэтому я иду спать. Завтра я исследую параметры, необходимые для CURLOPT_WRITEFUNCTION ...