自己编译的curl库

01 问题 自己编译libcurl库

默认curl是不支持ssl的,需要自己勾选,并配置对应ssl代码。
一般编译都需要支持ssl,大多选择openssl开源库。
可自行编译。编译的时候,最好勾选testing选项,来编译测试文件,这样编译研究各种测试用例。

这里写图片描述

勾选cmake中的 ENABLE_THREADED_RESOLVER 选项 。
并且注释掉代码中的

        //curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
        //curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);

release版本不再崩溃。

参考:
https://blog.csdn.net/delphiwcdj/article/details/18284429
https://blog.csdn.net/u013317006/article/details/20696261
https://blog.csdn.net/xuheazx/article/details/52689327

02 解决办法

curl-get.h

#pragma once
#include <string>

bool curl_get_req(const std::string &url, std::string &sBody, std::string &sHeader);

bool curl_get_req2(const std::string &url, std::string &sHeader, std::string &sBody);

curl-get.cpp

#include <iostream>  
#include <string>  
#include "curl/curl.h"  
using namespace std;

#pragma comment(lib, "ws2_32.lib")  
#pragma comment(lib, "wldap32.lib")  
#pragma comment(lib, "libcurl.lib")  

// WIN32 NDEBUG
// https://blog.csdn.net/u013317006/article/details/20696261

// https://blog.csdn.net/xuheazx/article/details/52689327
//libcurl 不支持异步 dns 解析时,会通过 signal 的方式实现 dns 解析设置超时, 
//signal 会导致多线程程序崩溃,后台服务通常都是多线程的,
//所以应该总是设置这个选项(但是 libcurl 不支持异步 dns 解析时,超时选项将被忽略)。
//可以通过运行 curl --version 命令或调用 curl_version 函数查看 libcurl 是否支持异步 dns 解析,
//调用 curl_version_info 函数还可以获得具体的 c - ares 库版本号。
//编译 libcurl 时,通过为 configure 指定 --enable - threaded - resolver 或 --enable - ares 选项启用异步 dns 解析。

// https://blog.csdn.net/delphiwcdj/article/details/18284429

size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream)
{
    string *str = (string*)stream;
    cout << *str << endl;
    (*str).append((char*)ptr, size*nmemb);
    return size * nmemb;
}

// 用这个函数会的 release 版本会导致进程退出
bool curl_get_req(const std::string &url, std::string &sHeader, std::string &sBody)
{
    CURL *curl = curl_easy_init();
    CURLcode res;
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
        curl_easy_setopt(curl, CURLOPT_HEADER, 0);
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&sBody);
        sHeader = "";
        
        res = curl_easy_perform(curl);
    }
    
    curl_easy_cleanup(curl);
    return true;
}

// 这种模式debug/release都正常
bool curl_get_req2(const std::string &url, std::string &sHeader, std::string &sBody)
{
    auto curl_deleter = [](CURL *curl) {curl_easy_cleanup(curl); };
    using Curl = unique_ptr<CURL, decltype(curl_deleter)>;
    Curl curl{ curl_easy_init(), curl_deleter };
    CURLcode res;
    if (curl)
    {
        curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, false);
        curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl.get(), CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl.get(), CURLOPT_NOSIGNAL, 1L);
        curl_easy_setopt(curl.get(), CURLOPT_HEADER, 0);
        curl_easy_setopt(curl.get(), CURLOPT_CONNECTTIMEOUT, 30);
        curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, 30);
        curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl.get(), CURLOPT_LOW_SPEED_TIME, 5);
        #ifdef CURL_DOES_CONVERSIONS
                curl_easy_setopt(curl.get(), CURLOPT_TRANSFERTEXT, 1L);
        #endif
        #if LIBCURL_VERSION_NUM >= 0x072400
                curl_easy_setopt(curl.get(), CURLOPT_SSL_ENABLE_ALPN, 0L);
        #endif
        curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, (void *)&sBody);
        sHeader = "";

        res = curl_easy_perform(curl.get());
    }

    return true;
}

##03 debug正常/release失败,不是这个库的问题

chromium 加载自己的dll,需要注意dll调用要符合windows api规范。
debug版本没有严格按照windows api规范,所以debug版本调用正常。
release版本则必须严格按照win api标准,尤其是内存分配。
比如:你不可以用std::string &params 作为dll的回参参数。而需要使用比如 char *params这种类型的,在dll函数外表分配内存的形式。(如果动态分配内存,必须自己严格释放)

另外,com 接口的使用也必须注意。

##04 遇到静态链接错误
如果是

__imp_curl_easy_init
__imp_curl_easy_setopt
__imp_curl_easy_perform

类型的链接错误,应该是没有加入预编译项:CURL_STATICLIB

如果出现

__imp_write
__imp_read
__imp_access

类型错误,应该是libcurl编译的时候,没有勾选CURL_STATIC_CRT

这里写图片描述

这里写图片描述

注意编译时zlib库需要使用动态加载vs dll的那种。否则会有vs库引入冲突。
在这里插入图片描述
如果引入 zlibstatic.lib和zlibstaticd.lib,会有vs 库的冲突。如下:

138>MSVCRT.lib(_chandler4gs_.obj) : error LNK2019: 无法解析的外部符号 __except_handler4_common,该符号在函数 __except_handler4 中被引用
138>D:\git\curl\build\vs2017\x86\tests\libtest\Release\lib650.exe : fatal error LNK1120: 1 个无法解析的外部命令
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值