s2013中,多行注释ctrl +k ctrl+c
取消注释ctrl+k ctrl +u
6.5 先是编写了一个动态链接库,编写一个C++项目,在这个项目中使用这个动态链接库
1、编写动态链接库
2、编写项目加载这个dll,分为三个部分
- C/C++常规,附加包含目录,找到你编写的那个动态链接库cpp的位置,可以是相对/绝对路径
- 链接器,常规,附加库目录
输入,附加依赖项
6.6
1、C/C+±》常规-》附加包含目录-》…/include/DataBus
//include/DataBus中包含所有的头文件, 对应包含两个字。
2、链接器-》常规-》附加库目录-》…/lib/Debug
//Debug中包含一些lib文件 以及 dll文件
3、链接器-》输入-》附加依赖项-》DataBus.lib
//DataBus.lib就是你想要使用的动态链接库
相关变量:
SolutionDir,解决方案目录
ConfigurationName(或Configuration),配置名,通常是Debug或者Release
ProjectName,项目名字
IntDir,编译器使用的中间目录,产生obj文件
OutDir,链接器使用的输出目录
ProjectDir,项目目录
TargetDir,目录输出文件所在目录
TargetExt,目录输出的扩展名
TargetFileName,目录输出文件名,包括扩展名
TargetName,目录输出名,不包括扩展名
TargetPath,目录输出文件的全部路径名
错误问题:DataBusSender.exe系统错误
由于找不到DataBus.dll,无法继续执行代码。重新安装程序可能会解决此问题
解决方案:项目属性->配置属性->常规->输出目录->
(
S
o
l
u
t
i
o
n
D
i
r
)
(SolutionDir)
(SolutionDir)(Configuration),这句话的理解的意思是:比如:文件夹DataBusSender与文件夹Debug为同级目录
将lib/Debug中的DataBus.dll复制到 外面Debug文件夹中
6.19 编写MyDll.dll 以及MyDllText.cpp中出现的问题
1、编写动态链接库MyDll.dll
Win32项目-》Dll 空项目-》
如果想要查看dll/lib等文件的输出目录:属性-》常规-》输出目录-》浏览,此处文件夹下就是dll/lib输出文件的位置;
2、关于如何编写动态链接库?
固定格式:
xxx.h
#ifdef MY_DLL_EXPORTS
#define MY_DLL_EXP __declspec(dllexport)
#else
#define MY_DLL_EXP __declspec(dllimport)
#endif
class MY_DLL_EXP HelloDll
{
//和正常的头文件 一样编写
};
属性-》c/c+±》预处理器-》预处理器定义-》编辑 添加宏MY_DLL_EXPORTS
在预编译器中定义宏MY_DLL_EXPORTS ,这样我们在编译的时候就会导出函数
xxx.cpp
#include “xxx.h”
.下面的内容 和其他的cpp编写一样
.
最后编译,就会在指定文件中出现你需要的dll和lib
3、编写的其他程序,如何调用这个dll
$(SolutionDir)指解决方案目录
(
C
o
n
f
i
g
u
r
a
t
i
o
n
)
指
代
运
行
目
录
,
就
是
D
e
b
u
g
或
者
R
e
l
e
a
s
e
建
立
项
目
,
项
目
属
性
(
如
果
需
要
使
用
这
个
d
l
l
,
需
要
进
行
配
置
属
性
)
1
)
c
/
c
+
+
−
》
常
规
−
》
附
加
包
含
目
录
−
》
找
到
文
件
夹
(
文
件
夹
中
有
动
态
链
接
库
的
头
文
件
)
c
/
c
+
+
−
》
常
规
−
》
附
加
包
含
目
录
−
》
编
辑
(Configuration)指代运行目录,就是Debug或者Release 建立项目,项目属性(如果需要使用这个dll,需要进行配置属性) 1) c/c++-》常规-》附加包含目录-》找到文件夹(文件夹中有动态链接库的头文件) c/c++-》常规-》附加包含目录-》编辑
(Configuration)指代运行目录,就是Debug或者Release建立项目,项目属性(如果需要使用这个dll,需要进行配置属性)1)c/c++−》常规−》附加包含目录−》找到文件夹(文件夹中有动态链接库的头文件)c/c++−》常规−》附加包含目录−》编辑(SolutionDir) $(Configuration)(编辑此处的值为刚才我们MyDll项目的输出目录即可,此处建议这么写 $(SolutionDir) $(Configuration)\,相对位置在项目转移时不容易出错 或者使用 …\ 表示)
相对路径 是 相对于你创建项目的文件夹的位置
2) 链接器-》常规-》附加库目录-》找到文件夹(文件夹中有lib和dll文件)
3) 链接器-》输入-》附加依赖项-》编辑 MyDll.lib
这些属性配置成功后,就开始编写项目:
此时只需要添加头文件 #include ”MyDll.h”
4、对于添加文件 方法总结:
1、 添加生成的dll、lib文件,可以
[1] 选择绝对路径,找到对应的Debug 或者 release
[2] 选择相对路径,相对路径开始 是从你创建项目的文件开始
[3] 将$(SolutionDir) $(Configuration)\粘贴过去,这个就代表以上路径。如果你编写dll的时候没有修改这边的路径
2、其他几个方面的配置,如上面陈述的内容相同。
5、将这个宏讲解一下
#ifdef MY_DLL_EXPORTS
#define MY_DLL_EXP __declspec(dllexport)
#else
#define MY_DLL_EXP __declspec(dllimport)
#endif
只要在预编译器中定义MY_DLL_EXPORTS宏,编译的时候就会导出函数
调用的客户端是没有这个宏MY_DLL_EXPORTS的,就会导入函数
6.20
关于Vs2013
[1] Debug与Release的区别:
Release中没有调试的信息,其生成的xxx.exe比Debug生成的xxx.exe小一点
[2] Win32与X64 32位与64位
64位兼容32位,64位其实就是将前面32位用0补齐;
调试F10(step over)与F11(step into)都是单步调试,区别在于F10单步调试是一步一步向前运行,遇到函数不进入函数体;F11也是单步调试,但是遇到函数进入函数体。
设置断点后,让程序代码运行至此处时自动停止。多练习。
编译到此处时,“暂停”按F5继续运行,如果不是函数,是不能进去查看的。
需要注意代码有没有执行执行这句话,可以看到问题。
对于属性赋值,可以把鼠标放在变量上,这样可以明显看到变量有没有变化。
按F10单步调试,黄色箭头表示已经运行
F11进入函数体,shift+F11退出函数体 或者进入函数体后 按F10一步一步进行,到达函数尾处,自然就会退出函数体
可以同时设置多个断点,设置断点就是调试到你设置断点函数处,会进入该函数(即使按的是F10)
调试的时候,一般需要看堆栈、线程、进程、内存等内容;
6.21
系统测试;
对于精度要求高的定时操作,使用函数QueryPerformanceFrequency()和 QueryPerformanceCounter()函数。
QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下:
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);
数据类型LARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构, 其具体用法根据编译器是否支持64位而定。该类型的定义如下:
typedef union _LARGE_INTEGER
{
struct
{
DWORD LowPart ;// 4字节整型数
LONG HighPart;// 4字节整型数
};
LONGLONG QuadPart ;// 8字节整型数
}LARGE_INTEGER ;
在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率, 然后在需要严格定时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差及时钟频率,计算出事件经 历的精确时间。下列代码实现1ms的精确定时:
LARGE_INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;// 获得初始值
do
{
QueryPerformanceCounter(&litmp);
QPart2 = litmp.QuadPart;//获得中止值
dfMinus = (double)(QPart2-QPart1);
dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
}while(dfTim<0.001);
其定时误差不超过1微秒,精度与CPU等机器配置有关。 下面的程序用来测试函数Sleep(100)的精确持续时间:
LARGE_INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;// 获得初始值
Sleep(100);
QueryPerformanceCounter(&litmp);
QPart2 = litmp.QuadPart;//获得中止值
dfMinus = (double)(QPart2-QPart1);
dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
由于Sleep()函数自身的误差,上述程序每次执行的结果都会有微小误差。下列代码实现1微秒的精确定时:
LARGE_INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;// 获得初始值
do
{
QueryPerformanceCounter(&litmp);
QPart2 = litmp.QuadPart;//获得中止值
dfMinus = (double)(QPart2-QPart1);
dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
}while(dfTim<0.000001);
其定时误差一般不超过0.5微秒,精度与CPU等机器配置有关、
7.2 c++中,右边大括号需要加分号的情况
定义结构、类、枚举类型时必须加分号;
数组变量在定义的同时用{}来初始化的话,加分号;