编译curl的动态库以及curl动态库的使用

1、编译curl静态库

1、从 https://github.com/curl/curl.git 拉取curl的源码,我是直接下载的zip包

2、本地解压zip包到对应的目录

3、根据情况打开curl-all.sln解决方案,这里使用的是curl\projects\Windows\VC7.1\curl-all.sln
若没有对应的目录和解决方案,则可以修改curl\projects\generate.bat文件,如下:

:parseArgs增加
else if /i "%~1" == "vc7.1" (
    set VERSION=VC7.1
:start增加
 if "%VERSION%" == "VC7.1" goto vc71
:vc71
  echo.

  if "%MODE%" == "GENERATE" (
    echo Generating VC7.1 project files
    call :generate vcproj1 Windows\VC7.1\src\curl.tmpl Windows\VC7.1\src\curl.vcproj
    call :generate vcproj1 Windows\VC7.1\lib\libcurl.tmpl Windows\VC7.1\lib\libcurl.vcproj
  ) else (
    echo Removing VC7.1 project files
    call :clean Windows\VC7.1\src\curl.vcproj
    call :clean Windows\VC7.1\lib\libcurl.vcproj
  )

  if not "%VERSION%" == "ALL" goto success

接着拷贝一份解决方案和项目到curl\projects\Windows\目录下,上面是VC7.1 的,因此增加curl\projects\Windows\VC7.1目录,里面存在对应的解决方案和项目即可

4、编译LIB Release、LIB Release-LIB OPENSSL、LIB Debug、LIB Debug-LIB OPENSSL的libcurl.lib文件,此时在目录下生成如下文件(生成的最终的文件名需要配置,否则都是libcurl.lib和libcurld.lib)
在这里插入图片描述
到这里,curl的静态库就编译完成了。

2、curl动态库的编译

curl支持生成动态库,也可以由用户通过加载libcurl.lib生成自定义的curl动态库。

1、直接编译curl源码

选择LIB Release、LIB Release-LIB OPENSSL、LIB Debug、LIB Debug-LIB OPENSSL4项编译对应的curl库即可。
用户直接加载dll就可以啦,如下:

#include "stdafx.h"
#include "curl/curl.h"

typedef CURLcode (*pcurl_global_init)(long flags);
typedef CURL* (*pcurl_easy_init)(void);

int _tmain(int argc, _TCHAR* argv[])
{
	CURLcode ret = CURLE_OK;
	CURL* curl = NULL;
	HMODULE hDll = LoadLibrary(L"H:\\Project\\testCurlDll\\lib\\libcurl.dll");
	pcurl_global_init global_init = (pcurl_global_init)GetProcAddress(hDll, "curl_global_init");
	if (NULL != global_init)
	{
		ret = global_init(CURL_GLOBAL_DEFAULT);
	}
	
	pcurl_easy_init easy_init = (pcurl_easy_init)GetProcAddress(hDll, "curl_easy_init");
	if (NULL != easy_init)
	{
		curl = easy_init();
	}


	system("pause");
	return 0;
}

2、用户生成自定义curl动态库

用户可以根据自己的需要,导出对应的curl的接口,实际上就是对curl函数的进一步封装。

2.1、用户根据自己的需要,列出需要使用的接口

如下:

#pragma once

#include "curl/curl.h"

class ICurl
{
public:
    virtual ~ICurl(){};

    virtual BOOL my_curl_global_init(long lFlags) = 0;
     
    virtual void my_curl_global_cleanup() = 0;

    virtual CURL* my_curl_easy_init() = 0;
 
   virtual struct my_curl_slist* curl_slist_append(struct curl_slist* pCurlList, const char *pContext) = 0;
 
   virtual CURLcode my_curl_easy_setopt(CURL *pCurl, CURLoption option, ...) = 0;
 
   virtual CURLcode my_curl_easy_perform(CURL *pCurl) = 0;

    virtual CURLcode my_curl_easy_getinfo(CURL *pCurl, CURLINFO info, ...) = 0;

    virtual void my_curl_slist_free_all(struct curl_slist* pCurlList) = 0;
 
    virtual void my_curl_easy_cleanup(CURL* pCurl) = 0;
 
   virtual CURLFORMcode my_curl_formadd(struct curl_httppost **httppost, struct curl_httppost **last_post, ...) = 0;

   virtual const char* my_curl_easy_strerror(CURLcode error) = 0;
};
2.2 实现上述的接口

主要是加载lib文件实现

#ifdef _DEBUG
#pragma comment(lib,"libcurlssld.lib")
#else
#pragma comment(lib,"libcurlssl.lib")
#endif

void CCurl::my_curl_global_cleanup()
{
	curl_global_cleanup();
}

如上,直接调用lib的函数实现即可。这里为什么用libcurlssl.lib(LIB Release-LIB OPENSSL)呢?这是为了让curl支持https通讯方式。如果我们中途需要切换为https通讯方式,但是使用的lib是LIB Release编译方式的,那在执行curl_formadd时会返回错误码:CURLE_UNSUPPORTED_PROTOCOL,意思是libcurl中不支持https

为了使用https,那就得让curl支持https,所以问题还是在curl上。我们知道https由2部分组成:http + ssl/tls,在http的基础上加了处理加解密信息,由此可知https传输的数据都是加密后的数据。因此我们只要编译支持ssl的curl库即可支持使用https。即LIB Release-LIB OPENSSL编译方式生成的libcurl.lib就能支持https。

2.3 接口均实现完成,点击编译即可
2.4 其他情况

1)出现

CCurl.obj : error LNK2001: unresolved external symbol __imp__FormAdd
1>CCurl.obj : error LNK2001: unresolved external symbol __imp__Curl_vsetopt
1>CCurl.obj : error LNK2001: unresolved external symbol __imp__curl_global_cleanup
1>CCurl.obj : error LNK2001: unresolved external symbol __imp__curl_slist_free_all
1>CCurl.obj : error LNK2001: unresolved external symbol __imp__curl_easy_init

原因是没有加上预编译头CURL_STATICLIB,右键工程——属性——C++——Preprocessor——Preprocessor Definitions加入CURL_STATICLIB即可

2)

curl_setup_once.h(274) : error C2628:<unnamed-tag>‘ followed by ‘bool‘ is illegal (did you forget a ‘;?)

这种情况在编译curl源码的静态库和动态库时不会出现,一般是在其他模块引用时会出现。这是因为curl源码中存在curl/lib/share.c/h,这2个文件和vs安装目录Microsoft Visual Studio 9.0\VC\include下的share.h同名并都被引用,因此编译时就出现了这个问题。解决办法就是修改一下curl源码库中curl/lib/share.c/h的文件名,可修改为curl_share.c/h,同时修改一下curl源码库中文件:
在这里插入图片描述
主要是将其中的#include "share.h"改为#include "curl_share.h"即可,重新编译一下LIB Release、LIB Release-LIB OPENSSL、LIB Debug、LIB Debug-LIB OPENSSL这4种curl库,完成之后再编译一下自己的dll模块,发现就没有错误了。

3、注意点

1、从定义的接口可知

virtual CURLcode my_curl_easy_setopt(CURL *pCurl, CURLoption option, ...) = 0;
virtual CURLFORMcode my_curl_formadd(struct curl_httppost **httppost, struct curl_httppost **last_post, ...) = 0;

curl_easy_setopt在curl源码中的实现是

va_list arg;
  CURLcode result;

  if(!data)
    return CURLE_BAD_FUNCTION_ARGUMENT;

  va_start(arg, tag);

  result = Curl_vsetopt(data, tag, arg);

  va_end(arg);
  return result;

curl_formadd在curl源码中的实现是

va_list arg;
  CURLFORMcode result;
  va_start(arg, last_post);
  result = FormAdd(httppost, last_post, arg);
  va_end(arg);
  return result;

由此可知源码中是直接通过va_list获取可变参数的,但这样的话,我们的自定义接口最后一个参数也是可变类型的,那我们怎么将这个值传给lib中的curl_formadd或者curl_easy_setop呢?如果我们在my_curl_easy_setop中使用va_list 获取可变参数列表,在lib中有调用va_list 获取一次,明显是不对的。那我们可以怎么做呢?
由curl源码可知这2个接口的实现,所以我们可以直接实现接口的功能,不调用curl库中对应的curl_easy_setop或curl_formadd就可以了。这个时候我们发现Curl_vsetopt和FormAdd不支持外部模块使用,这就好办了,我们可以在curl/include/curl/curl.h中添加这2个函数的声明,如下:

CURL_EXTERN CURLFORMcode FormAdd(struct curl_httppost **httppost, struct curl_httppost **last_post, va_list params);

CURL_EXTERN CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list arg);

这个时候还要将FormAdd的源代码处的static去掉
重新编译后就生成libcurl库,这个时候外部模块就可以使用FormAdd和Curl_vsetopt啦。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值