目录

第1章编译    2

1.1 简介    2

1.2 下载    3

1.3 解决方案    4

1.4 创建项目    5

1.5 复制文件树    6

1.6 不使用预编译头文件    8

1.7 包含目录    9

1.8 定义宏    10

1.9 编译前事件    11

1.10 修改 obj 的位置    13

1.11 编译yasm    14

1.12 编译汇编代码    15

1.12.1 Custom Build    15

1.12.2 .rules文件    17

1.12.3 .targets文件    20

1.13 替换long long    23

1.14 strnlen函数    23

第1章编译

1.1 简介

MPIR 是一个开源的多精度整数和有理数计算库,基于 GMP 库开发。它有什么用呢?

如下图所示,笔者在推导缓和曲线弦长随弧长变化的函数时,得到了一个递推公式。

图1.1

递推公式如下:

可见的计算只涉及到分数(有理数)的四则运算,是比较简单的。只是随着的增大,运算量越来越大,手工计算会越来越困难。

上述公式可以编程实现。C/C++的基本数据类型中,使用double表示是比较恰当的。double是有误差的,而且的计算误差会积累,随着的增大的计算误差会越来越大。

借助MPIR的有理数计算功能,可以解决上述问题。的前几项见下表:

n

系数

0

1

1

-1/90

2

1/22680

3

-79/2043241200

4

2633/12504636144000

5

1215749/1646485441080480000

6

48316241/15905049360837436800000

7

193921367/49059847710292202784000000

8

-73267589502073/927478383356982505319631360000000

MPIR是从GMP移植而来的。因为GMP主要是针对于Unix、Linux操作系统的,使用VC++编译比较困难。MPIR的主要工作其实就是把GMP移植到Windows操作系统,使得VC++能够编译。

1.2 下载

浏览网址http://www.mpir.org/,下载mpir-2.7.0.zip,然后解压到W:\mpir\v2.7.0\mpir。目录结构如下图所示:

图1.2

1.3 解决方案

mpir 2.7.0自带了四个Visual Studio 解决方案,如下所示:

W:\mpir\v2.7.0\mpir\build.vc10\mpir.sln            使用vc2010打开

W:\mpir\v2.7.0\mpir\build.vc11\mpir.sln            使用vc2012打开

W:\mpir\v2.7.0\mpir\build.vc12\mpir.sln            使用vc2013打开

W:\mpir\v2.7.0\mpir\build.vc14\mpir.sln            使用vc2015打开

使用vc2010打开mpir.sln后,可以看到有七个项目,如下图所示:

图1.3

这七个项目的区别如下:

dll_mpir_gc        生成动态库,不使用汇编代码

dll_mpir_p3        生成动态库,含32位汇编代码(奔腾3)

dll_mpir_core2        生成动态库,含64位汇编代码(酷睿2)

lib_mpir_cxx        生成静态库,不使用汇编代码

lib_mpir_gc        生成静态库,不使用汇编代码

lib_mpir_p3        生成静态库,含32位汇编代码(奔腾3)

lib_mpir_core2        生成静态库,含64位汇编代码(酷睿2)

mpir有两套API:C API和C++ API。前者可用于C和C++,后者只能用于C++。lib_mpir_gc、lib_mpir_p3、lib_mpir_core2只含有C API;lib_mpir_cxx只含有C++ API;dll_mpir_gc、dll_mpir_p3、dll_mpir_core2既有C API又有C++ API。

从兼容性考虑,建议不要使用汇编代码。只有在对速度要求特别高的情况下,需要考虑使用汇编代码。

1.4 创建项目

为了使用vc6~vc2008编译mpir 2.7.0,需要创建项目。

笔者在W:\mpir\v2.7.0\vc目录下创建了11个目录,如下图所示。

make-dll-c        将创建动态库,只使用c语言

make-dll-asm32        将创建动态库,使用32位汇编代码

make-dll-asm64        将创建动态库,使用64位汇编代码

make-libS-*        将创建静态库,C运行时库为单线程

make-libT-*        将创建静态库,C运行时库为多线程

make-libD-*        将创建静态库,C运行时库为多线程DLL

图1.4

每个目录下,又有多个子目录,如下图所示。如:使用vc6编译请进入vc6目录。

图1.5

1.5 复制文件树

W:\mpir\v2.7.0\mpir\build.vc10\mpir.sln里每个项目都有文件树。如下图所示。现在要把这些项目的文件树复制到上一节新建的项目里。

图1.6

可以手工添加,只不过五百多个文件添加起来还是很繁琐的。可以使用vcHelper来完成此项繁琐的工作。如下图所示,vcHelper把W:\mpir\v2.7.0\mpir\build.vc10\dll_mpir_gc\dll_mpir_gc.vcxproj里的文件树复制到W:\mpir\v2.7.0\vc\make-dll-c\vc6\mpir.dsp。

图1.7

需要复制的文件树如下表所示:

从 W:\mpir\v2.7.0\mpir\build.vc10\dll_mpir_gc\dll_mpir_gc.vcxproj 复制到

W:\mpir\v2.7.0\vc\make-dll-c\vc6\mpir.dsp

W:\mpir\v2.7.0\vc\make-libD-c\vc6\mpirD.dsp

W:\mpir\v2.7.0\vc\make-libS-c\vc6\mpirS.dsp

W:\mpir\v2.7.0\vc\make-libT-c\vc6\mpirT.dsp

从 W:\mpir\v2.7.0\mpir\build.vc10\dll_mpir_p3\dll_mpir_p3.vcxproj 复制到

W:\mpir\v2.7.0\vc\make-dll-asm32\vc6\mpir.dsp

W:\mpir\v2.7.0\vc\make-libD-asm32\vc6\mpirD.dsp

W:\mpir\v2.7.0\vc\make-libS-asm32\vc6\mpirS.dsp

W:\mpir\v2.7.0\vc\make-libT-asm32\vc6\mpirT.dsp

从 W:\mpir\v2.7.0\mpir\build.vc10\dll_mpir_core2\dll_mpir_core2.vcxproj 复制到

W:\mpir\v2.7.0\vc\make-dll-asm64\vc2008\mpir.dsp

W:\mpir\v2.7.0\vc\make-libD-asm64\vc2008\mpirD.dsp

W:\mpir\v2.7.0\vc\make-libS-asm64\vc2008\mpirS.dsp

W:\mpir\v2.7.0\vc\make-libT-asm64\vc2008\mpirT.dsp

vcHelper的下载:访问http://pan.baidu.com/s/1gd7XDkf 然后进入public\Tools\vcHelper下载压缩包。

1.6 不使用预编译头文件

设置VC++,编译时不使用预编译头文件。

VC++6.0的设置如下图所示:

图1.8

VC++.NET的设置如下图所示:

图1.9

1.7 包含目录

编译.c文件时,需要文件W:\mpir\v2.7.0\mpir\mpir.h。该文件相对于VC++6.0项目文件(W:\mpir\v2.7.0\vc\make-dll-c\vc6\mpir.dsp)的相对路径为../../../mpir

VC++6.0的具体配置如下:

图1.10

VC++.NET的配置如下

图1.11

1.8 定义宏

需要定义宏:HAVE_CONFIG_H,不过它似乎没有什么实质作用。

编译生成动态库,还需要定义宏MSC_BUILD_DLL。它用来导出mpir的API函数。

VC++6.0的配置如下:

图1.12

VC++.NET的配置如下。vc2002~vc2008不能选择All Configuration,vc2010后可以选择All Configuration了。

图1.13

1.9 编译前事件

编译前,需要执行"编译前事件"。下图是VC++.NET的配置:

图1.14

上图表示编译前将执行两条命令:

"cd ..\..\..\mpir\build.vc10"表示设置..\..\..\mpir\build.vc10为当前目录。这是相对于W:\mpir\v2.7.0\vc\make-dll-c\vc6\mpir.dsp的目录,换成绝对目录就是W:\mpir\v2.7.0\mpir\build.vc10

"prebuild gc Win32"表示运行当前目录下的prebuild.bat文件,也就是运行W:\mpir\v2.7.0\mpir\build.vc10\prebuild.bat。gc和Win32是传递给prebuild.bat的两个参数。第一个参数有三个选项:gc、p3、core2,分别表示不使用汇编代码、使用32位汇编代码、使用64位汇编代码。第二个参数有两个选项:Win32、x64,分别表示32位、64位平台。

VC++6.0不支持"编译前事件",可以设置gmp-h.in文件的Custom Build,如下图所示:

图1.15

编译时,只要gmp-h.in是第一个被编译的,那么"cd ..\..\..\mpir\build.vc10"和"prebuild gc Win32"就会被执行,相当于"编译前事件"。

prebuild.bat的内容有些复杂,笔者并没有完全理解,只知道"prebuild.bat gc Win32"执行后将在W:\mpir\v2.7.0\mpir目录下生成五个文件:config.h、gmp.h、gmp-mparam.h、longlong.h、mpir.h。这些都是编译时需要的文件。

1.10 修改 obj 的位置

mpf、mpn、mpq、mpz下有很多重名的.c文件,编译时它们将生成重名的.obj文件。这些重名的.obj文件不能放在同一目录下,因此需要修改mpf、mpn、mpq、mpz这四个目录下所有.c文件生成的.obj文件的存放目录。

对于VC++6.0,设置如下图所示。mpf目录下的.c文件生成的.obj文件,原存放目录为 Temp\DU,现存放目录为Temp\DU\mpf。

图1.16

对于VC++.NET,设置如下图所示。mpf目录下的.c文件生成的.obj文件,原存放目录为$(IntDir)\,现存放目录为$(IntDir)\mpf\。注意:$(IntDir)\mpf\最后的\一定不能少,因为$(IntDir)\mpf会被当做文件,而$(IntDir)\mpf\才会被当做目录。

图1.17

根据上面两张图的配置,再修改mpn、mpq、mpz目录下.c文件的配置。

1.11 编译yasm

不需要编译汇编代码的,请跳过本节。

编译汇编代码需要yasm。mpir 2.7.0自带了yasm源代码,如下所示:

W:\mpir\v2.7.0\mpir\yasm\Mkfiles\vc9\yasm.sln            使用vc2008编译

W:\mpir\v2.7.0\mpir\yasm\Mkfiles\vc10\yasm.sln            使用vc2010编译

如果需要最新版本的yasm,可到如下网址下载:

http://www.tortall.net/projects/yasm/

http://yasm.tortall.net/

使用vc2010打开W:\mpir\v2.7.0\mpir\yasm\Mkfiles\vc10\yasm.sln。选择Win32 Release,然后鼠标右键单击"vsyasm"在弹出菜单中单击【Rebuild】。如下图所示。

编译时将会执行Python脚本文件W:\mpir\v2.7.0\mpir\yasm\modules\arch\x86\gen_x86_insn.py。笔者不清楚该脚本做了哪些工作,经测试发现不执行该脚本也不会影响最终exe文件的生成。

图1.18

编译生成的文件是W:\mpir\v2.7.0\mpir\yasm\Mkfiles\vc10\Win32\Release\vsyasm.exe。VC++可以调用该程序编译汇编代码。

1.12 编译汇编代码

不需要编译汇编代码的,请跳过本节。

VC++调用yasm编译汇编代码有三种方法:Custom Build、.rules文件、.targets文件。

1.12.1 Custom Build

Custom Build的优点是适用面广,vc6~vc2015都能使用;缺点是修改命令行参数稍显麻烦。

下图是mpn\yasm\*.asm的Custom Build配置:

图1.19

Outputs是编译*.asm后的输出文件,连接时会用到此文件。上图的设置为"$(IntDir)\$(InputName).obj"其中$(IntDir)是编译时的临时目录,$(InputName)是编译.asm文件名,如:编译add_n.asm时,$(InputName)就是add_n。

Commands是vsyasm.exe的命令行,具体如下:

..\..\..\mpir\yasm\Mkfiles\vc10\Win32\Release\vsyasm.exe -Xvc -f Win32 -g cv8 -d "DLL" -o "$(IntDir)\\" -rnasm -pnasm $(InputPath)

..\..\..\mpir\yasm\Mkfiles\vc10\Win32\Release\vsyasm.exe是W:\mpir\v2.7.0\mpir\yasm\Mkfiles\vc10\Win32\Release\vsyasm.exe相对于W:\mpir\v2.7.0\vc\make-dll-asm32\vc6\mpir.dsp的相对路径。

-Xvc 是错误信息显示格式。对于gcc编译器可设置为 -Xgcc 或 -Xgnu。

-f Win32 表明是32位平台,对于64位平台可指定为-f x64

-g cv8 用来生成调试信息,这种调试信息不能被 vc6 识别,所以使用vc6编译.asm文件时,请去除该选项。

-o "$(IntDir)\\"表示将在目录$(IntDir)里生成.obj文件。注意$(IntDir)后面的两个反斜杠一个都不能少。

$(InputPath)表示输入文件,如:add_n.asm、addmul_1.asm……

这里需要说明一下vc6里Custom Build的编译顺序。因为vc6不支持"编译前事件",可使用Custom Build代替"编译前事件",此时编译顺序就显得非常重要了。笔者经实验得到以下规律(并不能确保它一定正确):

1、Custom Build比.c或.cpp的编译要早;

2、在IDE里先后设置文件A、B的Custom Build,则编译时的顺序为逆序,即先编译B再编译A;

3、初次打开.dsp文件,编译顺序是文件在.dsp里的相反顺序。如:.dsp文件里从上到下依次有A、B需要Custom Build,那么编译时先编译B再编译A。

在图1.15中,gmp-h.in在.dsp文件里是最后一个文件,因此Custom Build时它总是第一个被编译。这样,就保证了它扮演"编译前事件"的角色。

1.12.2 .rules文件

vc2005和vc2008可以使用. rules文件。使用vc2008打开W:\mpir\v2.7.0\vc\make-dll-asm32\vc2008\mpir.sln,鼠标右键单击mpir项目,弹出菜单中单击【Custom Build Rules...】菜单项

图1.20

弹出如下界面,请单击"Find Existing..."按钮。

图1.21

请载入W:\mpir\v2.7.0\mpir\yasm\Mkfiles\vc9\yasm.rules文件,如下图所示:

图1.22

下图所示界面,请单击"否"按钮。

图1.23

下图所示界面内,请勾选"Yasm",然后单击"OK"按钮。

图1.24

此时查看mpir项目属性,可以看到配置里多了一项"Yasm Assembler",可以在这里对Yasm的命令行参数进行配置。如下图所示:

图1.25

再查看某个.asm文件的属性,可以看到它被自动关联到Yasm Assembler,也就是说编译.asm文件时将使用Yasm Assembler来编译。如下图所示:

图1.26

1.12.3 .targets文件

从vc2010开始. rules文件被.targets文件代替。使用vc2010打开W:\mpir\v2.7.0\vc\make-dll-asm32\vc2010\mpir.sln,鼠标右键单击mpir项目,弹出菜单中单击【Build Customization...】菜单项

图1.27

同样是单击"Find Existing..."按钮

图1.28

请载入W:\mpir\v2.7.0\mpir\yasm\Mkfiles\vc10\vsyasm.targets文件,如下图所示:

图1.29

下图所示界面,请单击"否"按钮。

图1.30

下图所示界面内,请勾选"vsyasm",然后单击"OK"按钮。

图1.31

注意:Yasm Assembler不会自动关联*.asm,需要将*.asm的Item Type属性更改为Yasm Assembler。

图1.32

1.13 替换long long

VC++6.0不支持long long,可用__int64替换它。具体如下:

1、替换 gmp-impl.h 里的 long long int 为 __int64;

修改后的两行代码如下:

typedef    __int64 DItype;

typedef unsigned __int64 UDItype;

2、替换printf\doprnt.c、printf\repl-vsnprintf.c、scanf\doscan.c里的long long 为 __int64。

1.14 strnlen函数

vc6、vc2002、vc2003不支持strnlen函数,所以需要修改代码。具体就是修改printf\repl-vsnprintf.c

修改前

修改后

#if ! HAVE_STRNLEN

static size_t

strnlen (const char *s, size_t n)

{

size_t i;

for (i = 0; i < n; i++)

if (s[i] == '\0')

break;

return i;

}

#endif

#if _MSC_VER <= 1310

static size_t strnlen(const char*str

,size_t num)

{

size_t n = 0;

if(str && num)

{

while(str[n])

{

if(++n >= num)

{

break;

}

}

}

return n;

}

#endif//#if _MSC_VER <= 1310

vc6、vc2002、vc2003的_MSC_VER分别为1200、1300、1310。从vc2005开始,VC++实现了strnlen函数。

VC++编译MPIR 2.7.0的更多相关文章

  1. vc编译 curl 7.36.0

    CURL邮件列表中提到官方最新版本的windows devel包中缺少文件,而我又用不到https,所以我就自己下载源码包来编译了 下载源码包:http://curl.haxx.se/download ...

  2. 用VC编译lua源码,生成lua语言的解释器和编译器

    用VC编译lua源码,生成lua语言的解释器和编译器 1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编 ...

  3. VC++编译zlib

    目录 第1章简介    1 第2章版本1.2.3    2 2.1 编译汇编代码    2 2.1.1 32位汇编    2 2.1.2 64位汇编    5 2.2 Visual C++ 6.0   ...

  4. VC++编译GSL

    目录 第1章 VC++    1 1.1 修改行结束符    1 1.2 修改#include "*.c" 为 #include "*.inl"    2 1. ...

  5. VC编译连接选项详解

    VC编译连接选项详解 大家可能一直在用VC开发软件,但是对于这个编译器却未必很了解.原因是多方面的.大多数情况下,我们只停留在“使用”它,而不会想去“了解”它.因为它只是一个工具,我们宁可把更多的精力 ...

  6. 迁移到MSYS2 与 Qt 工具链注意的几个事情(g++在链接时,符号依赖项查找遵循从左至右的顺序,但qmake会自动合并造成错误。使用脚本给Mingw32-make创造出一个局部的VC编译环境)

    Microsoft Visual Studio 2015社区版提供了强大的开发体验,且 Qt 提供了预编译版本.然而,由于客户提出兼容Windows XP ~ Windows 8.1 这样宽泛的环境要 ...

  7. Windows VS2017 编译 libssh2 1.7.0(执行命令、文件上传、下载)

    下载安装 OpenSSL 要编译 libssh2,必须先编译好 OpenSSL 的静态库,直接从 http://slproweb.com/products/Win32OpenSSL.html 下载已经 ...

  8. VC 编译 MATLAB 的 mex 文件

    VC 编译 MATLAB 的 mex 文件mex 文件是 MATLAB 调用其他程序设计语言程序或算法的接口.在 Windows 环境中,mex 文件是扩展文件名为 DLL 的动态链接库,可以在 m ...

  9. CentOS 7.0编译安装Nginx1.6.0+MySQL5.6.19+PHP5.5.14

    准备篇: CentOS 7.0系统安装配置图解教程 http://www.osyunwei.com/archives/7829.html 一.配置防火墙,开启80端口.3306端口 CentOS 7. ...

随机推荐

  1. Android中直播视频技术探究之---视频直播服务端环境搭建(Nginx+RTMP)

    一.前言 前面介绍了Android中视频直播中的一个重要类ByteBuffer,不了解的同学可以 点击查看 到这里开始,我们开始动手开发了,因为我们后续肯定是需要直播视频功能,然后把视频推流到服务端, ...

  2. 2016年11月28日 星期一 --出埃及记 Exodus 20:19

    2016年11月28日 星期一 --出埃及记 Exodus 20:19 and said to Moses, "Speak to us yourself and we will listen ...

  3. IDEA打war包

    一 第一步创建一个web application:expolded 选择当前项目 二 新建一个web application: Archive 选择刚刚新建的Expoded  “For ‘...... ...

  4. ocruntime

    原作: http://www.jianshu.com/p/25a319aee33d 三种方法的选择 Runtime提供三种方式来将原来的方法实现代替掉,那该怎样选择它们呢? Method Resolu ...

  5. Java CSV操作(导出和导入)

    Java CSV操作(导出和导入)  CSV是逗号分隔文件(Comma Separated Values)的首字母英文缩写,是一种用来存储数据的纯文本格式,通常用于电子表格或数据库软件.在 CSV文件 ...

  6. Linux运维命令之一

    释放内存:syncecho 3 > /proc/sys/vm/drop_caches Linux查看Dell服务器型号命令:dmidecode | grep "Product Name ...

  7. [Cocoa]深入浅出 Cocoa 之 Core Data(1)- 框架详解

    Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂.Core Data 相关的类比较多,初学者往往不太容易弄懂.计划用三个教程来讲解这一部分: 框架详解 ...

  8. Cheatsheet: 2013 08.01 ~ 08.13

    Mobile Objective C Blocks: Summary, Syntax & Best Practices Android SDK: Create an Arithmetic Ga ...

  9. spring+hibernate 实体类注解问题

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.Ann ...

  10. window--窗口

    创建窗口 1. 通过标签窗口窗口. <div id="win" class="easyui-window" title="My Window&q ...