Я скомпилировал libcurl в Windows, используя компилятор Visual C ++ в dll. В дополнение к скомпилированному исходному коду libcurl, эта dll содержит простую тестовую программу, которая выглядит следующим образом:
Заголовок (HttpClient.h
):
#pragma once
#include <string>
#include "curl/curl.h"
namespace My::Project
{
class HttpClient
{
public:
HttpClient();
~HttpClient();
std::string Get(std::string address);
private:
CURL* easy_handle;
};
}
Реализация (HttpClient.cpp
):
#include "HttpClient.h"
#include <iostream>
using namespace My::Project
HttpClient::HttpClient()
{
easy_handle = curl_easy_init();
curl_global_init(CURL_GLOBAL_ALL);
}
HttpClient::~HttpClient()
{
curl_global_cleanup();
}
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
std::string HttpClient::Get(std::string address)
{
std::string html;
curl_easy_setopt(easy_handle, CURLOPT_URL, address.c_str());
curl_easy_setopt(easy_handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &html);
CURLcode returnValue = curl_easy_perform(easy_handle);
if(returnValue != CURLE_OK)
{
html = "Failed to retrieve HTML";
}
curl_easy_cleanup(easy_handle);
return html;
}
Эта тестовая программа прекрасно компилируется.
(Кстати: я знаю, что curl_global_init
и curl_global_cleanup
должны вызываться только один раз. Это всего лишь тестовая программа ...)
Теперь я хочу сослаться на эту dll в другой dll, создать экземпляр класса HttpClient
и использовать его следующим образом:
#include "<relative-path>/HttpClient.h"
using namespace My::Project;
// Within a constructor of another class
HttpClient client;
std::string html = client.Get("https://www.google.com/");
Вызов компилятора, использованный для компиляции второй DLL, выглядит следующим образом:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\bin\HostX86\x64\CL.exe
/c
/I<project path>
/I"Generated Files\\"
/Iobj\Debug\x64\
/I<path to curl source>\curl\include
/ZI
/JMC
/ZW
/ZW:nostdlib
/nologo
/W3
/WX-
/diagnostics:column
/sdl
/MP
/Od
/Oy-
/D _WINRT_DLL
/D _WINDLL
/D _UNICODE
/D UNICODE
/D _DEBUG
/D WINAPI_FAMILY=WINAPI_FAMILY_APP
/D __WRL_NO_DEFAULT_LIB__
/Gm-
/EHsc
/RTC1
/MDd
/GS
/fp:precise
/Zc:wchar_t
/Zc:forScope
/Zc:inline
/std:c++17
/Yu"pch.h"
/Fp"obj\Debug\x64\pch.pch"
/Fo"obj\Debug\x64\\"
/Fd"obj\Debug\x64\vc142.pdb"
/Gd
/TP
/wd28204
/FU"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\lib\x86\store\references\platform.winmd"
/FU"<other winmd files>
/analyze-
/FC
/errorReport:prompt
/bigobj
<path to cpp file invoking HttpClient>
Однако попытка скомпилировать второй dll приводит к тому, что компилятор Visual C ++ выдает следующие ошибки:
<path to curl source>\curl\include\curl\curl.h(134,29): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
<path to curl source>\curl\include\curl\curl.h(134,16): error C2146: syntax error: missing ';' before identifier 'curl_socket_t'
<path to curl source>\curl\include\curl\curl.h(397,52): error C2061: syntax error: identifier 'curl_socket_t'
<path to curl source>\curl\include\curl\curl.h(407,23): error C2079: 'curl_sockaddr::addr' uses undefined struct 'sockaddr'
<path to curl source>\curl\include\curl\curl.h(411,3): error C2065: 'curl_opensocket_callback': undeclared identifier
<path to curl source>\curl\include\curl\curl.h(411,27): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
<path to curl source>\curl\include\curl\curl.h(411,27): error C2378: 'curl_socket_t': redefinition; symbol cannot be overloaded with a typedef
<path to curl source>\curl\include\curl\curl.h(134): message : see declaration of 'curl_socket_t'
<path to curl source>\curl\include\curl\curl.h(411,28): error C2513: 'int': no variable declared before '='
<path to curl source>\curl\include\curl\curl.h(411,28): error C2143: syntax error: missing ';' before '('
<path to curl source>\curl\include\curl\curl.h(411,34): error C2062: type 'void' unexpected
<path to curl source>\curl\include\curl\curl.h(416,59): error C2061: syntax error: identifier 'curl_socket_t'
<path to curl source>\curl\include\curl\multi.h(113,19): error C3646: 'fd': unknown override specifier
<path to curl source>\curl\include\curl\multi.h(113,19): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
<path to curl source>\curl\include\curl\multi.h(157,47): error C2061: syntax error: identifier 'fd_set'
<path to curl source>\curl\include\curl\multi.h(271,51): error C2061: syntax error: identifier 'curl_socket_t'
<path to curl source>\curl\include\curl\multi.h(292,76): error C2061: syntax error: identifier 'curl_socket_t'
<path to curl source>\curl\include\curl\multi.h(296,62): error C2061: syntax error: identifier 'curl_socket_t'
<path to curl source>\curl\include\curl\multi.h(410,55): error C2061: syntax error: identifier 'curl_socket_t'
Вслед за первым сообщением об ошибке я получаю следующий фрагмент кода в curl.h
:
131: #ifndef curl_socket_typedef
132: /* socket typedef */
133: #if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
134: typedef SOCKET curl_socket_t;
135: #define CURL_SOCKET_BAD INVALID_SOCKET
136: #else
137: typedef int curl_socket_t;
138: #define CURL_SOCKET_BAD -1
139: #endif
140: #define curl_socket_typedef
141: #endif /* curl_socket_typedef */
Таким образом, компилятор по существу жалуется на следующую строку:
134: typedef SOCKET curl_socket_t;
Однако в настоящее время я не знаю, в чем именно проблема. Один и тот же код прекрасно компилируется с Clang для Android и iOS.
Кто-нибудь видит, что нужно сделать, чтобы компилировать это с Visual C ++?