在网上浏览了很多资料,之前做过一次,dll没弄成,这次又弄了一遍,总结一下
我的系统与环境
- win10 1607
- x64的处理器与操作系统
- vs2017
注意:本文章中的(?)表示作者也不确定,<…>表示使用…说明的东西替换这个<>
链接
curl官网:curl.se(可能打不开,不行就用curl的github)
curl官网下载(代码压缩包):https://curl.se/download/
openSSL官网:https://www.openssl.org/
openSSL下载(代码压缩包):https://www.openssl.org/source/
perl官网:https://www.perl.org/
编译
OpenSSL
- 这一部分问题较多,参考“可能的问题”
- 安装VisualStudio(选择curl支持的版本(打开项目后不提示生成工具版本不支持就行),比如7.77.0的projects文件夹下面最高是VC15,就对应vs2017)
- 下载并安装perl(如果提示错误可能是已安装,右键.msi先卸载即可)(ActivePerl:不要安装最新版(使用命令的那个),否则很难卸载,安装下面的msi安装包版,最好是StrawberryPerl)、openSSL代码
- 打开(必须是管理员(?))x86 Native Tools Command Prompt for VS <版本>(或者VS 2017的x64本机工具命令提示(?))
- 定位到解压的openSSL目录下
- 使用perl Configure no-shared(编译lib,去掉就是dll(应该用shared才是dll(?))) no-asm(没有安装nasm就加上,使用no-asm的版本暂未测试) VC-WIN32(选择编译器,64位可使用VC-WIN64A) --debug(如果想要release就去掉) --prefix=<导出目录> --openssldir=<导出目录>
- 完成后输入nmake(开始编译),时间较长
- 完成后输入nmake install(开始导出文件),时间较长
libcurl
- 把<导出目录>/include下的文件复制到<curl解压目录/include>下
- 用vs打开<curl解压目录>/projects/Windows/VC<vc版本>下面的一个项目文件,选择模式和位数,生成解决方案
可能的问题
- 编译OpenSSL时出现“找不到Win32::Console module”:
用ActivePerl:安装Win32::Console module(未找到方法) 用strawberryPerl:就行了 - 编译OpenSSL时出现“模块计算机类型与目标计算机类型不相符”:
x86与x64不兼容-用“适用于 VS 2017 的 x86_x64 兼容工具命令提示”(大概是把86转换成64的意思) - 配置编译器时出错:
检查命令行语法 - 编译OpenSSL时出现“忽略未知参数:<用来设置导出路径的prefix和openssldir>”
不管它,引用OpenSSL文档对这两个参数的默认值说明:
For VC-WIN32, the following defaults are use:
PREFIX: %ProgramFiles(x86)%\OpenSSL
OPENSSLDIR: %CommonProgramFiles(x86)%\SSL
For VC-WIN64, the following defaults are use:
PREFIX: %ProgramW6432%\OpenSSL
OPENSSLDIR: %CommonProgramW6432%\SSL - nmake/nmake test/nmake install一直不结束
就是慢,可能要30min,要是自己感觉没问题就不test了真的很慢,install时看到导出目录有自己要的东西就可以Ctrl+C了,后面的可以不运行(?) - 输入nmake后出现“fatal error U1001: 语法错误: 宏中的非法字符“…””之类的语法错误:
OpenSSL1.0.x(和1.1.x(?))有该问题,可能的解决方法:输入ms\do_ms.bat(复制Makefile数据(?),运行类似的就行,比如ms\do_nasm.bat,如果有nasm的话),再把nmake及后面用到的其他nmake命令都换成nmake -f ms\nt.mak(动态库就是ntdll.msk)
更好的解决方法:换OpenSSL3.x.x - 配置编译器位数是否影响生成的OpenSSL库位数:OpenSSL文档说影响
- 生成curl项目时出现“无法打开包含文件:“<文件名>.c””:没有复制OpenSSL导出的include文件(注意这个问题仅限.c文件)
- 生成curl项目时出现“无法打开文件:“<文件名>.lib””(注意这个问题仅限.lib文件且应该在生成的link阶段):
看看保持位置上面写的是解决方案中的哪个项目,curl还是libcurl,复制OpenSSL生成的.lib到curl-<版本>\projects\Windows\VC<版本><lib或src(看看里面的项目文件名是什么)> - 生成curl项目时出现“无法打开文件:“libcurl.lib””:其他curl项目生成问题解决后就会自动解决
- 生成curl项目时出现“无法解析的外部符号…”:(注意不是在自己的项目使用curl时出现的)
OpenSSL版本与curl版本或配置不匹配导致curl库或OpenSSL库引用了另一个没有的符号,确定OpenSSL和curl都是自己这次编译的应该就没问题了
使用
- 复制curl解压目录下面的include文件夹(编译时把openssl文件夹复制它下面了)到项目中
- 在代码中
#include "....../include/curl.h"
下面分lib/dll
lib
- 复制libcurl.lib、libcrypto.lib、libssl.lib到项目中
注意:分清楚自己编译的curl和OpenSSL版本,lib和dll版的curl和OpenSSL最后生成的lib文件都不一样
- 在代码中:
#pragma comment(lib, "....../libcurl.lib")
#pragma comment(lib, "....../libcrypto.lib")
#pragma comment(lib, "....../libssl.lib")
- 确保ws2_32.lib、wldap32.lib、crypt32.lib已在项目中引用
- 测试curl是否可以使用
dll(显式链接)
- 复制libcurl.dll、libcrypto-3-x64.dll、libssl-3-x64.dll到项目中
LoadLibrary()
加载libcurl.dll(不会自己学一下)
注意:libcurl.dll会自动加载libcrypto-3-x64.dll、libssl-3-x64.dll
自动加载位置不是libcurl.dll所在目录,而是exe文件的运行起始目录
- 检查是否可以从dll调用函数
-
这里包含curl.h的目的与lib版的不同,这里不需要curl函数的声明,需要的是CURLcode等结果的定义,因为使用函数指针时需要函数的返回值和参数类型
-
从dll获取函数地址时一定要写对函数名(就是curl_easy_init之类的)
-
lib和dll版的调试时可以加载curl编译时生成的.pdb符号文件(符号文件必须位于curl编译时生成的位置(?)),对curl的调试很有用