关于动态链接库dll

s2013中,多行注释ctrl +k ctrl+c
取消注释ctrl+k ctrl +u

6.5 先是编写了一个动态链接库,编写一个C++项目,在这个项目中使用这个动态链接库
1、编写动态链接库
2、编写项目加载这个dll,分为三个部分

  1. C/C++常规,附加包含目录,找到你编写的那个动态链接库cpp的位置,可以是相对/绝对路径
  2. 链接器,常规,附加库目录
    输入,附加依赖项

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)DebugRelease使dll,1c/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++中,右边大括号需要加分号的情况
定义结构、类、枚举类型时必须加分号;
数组变量在定义的同时用{}来初始化的话,加分号;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值