win32学习记录day-11

  • 静态库程序 - 运行时不存在,会被链接
    到可执行文件或者动态库中,目标程序的归档。
    文件扩展名:LIB
  • 动态库程序 - 运行时独立存在,不会被链接到可执行文件或其他动态库中。
    文件扩展名:DLL

静态库程序

  1. 静态库特点
  • 运行时不存在
  • 链接到可执行文件或者动态库中
  • 目标程序的归档
  1. C语言静态库

    • 静态库的创建
      • 建项目
      • 添加库程序,源文件使用C文件
    • 库的路径设置
      • 项目的“Settings”中设置库的路径
      • 可以使用 pragma 关键字设置
    • c语言静态库的使用
      建立一个C文件,可以在文件中直接使用C库函数,不需要头文件。C编译器只是根据库函数名称,在库中找到对应的函数代码,进行链接。
  2. C++语言的静态库
    • 静态库的建立
      • 建立项目
      • 添加库程序,源文件使用CPP文件
    • 库的导入
      • 项目的“Setting”中设置库的路径
      • 可以使用 pragma 关键字设置
    • 注意
      在CPP环境使用C静态库,库中函数原型定义要增加 extern “C”, 例如:extern "C" int Add(... );

动态库程序

  1. 动态库特点
    • 运行时独立存在
    • 不会链接到执行程序
    • 使用时要加载(使动态库程序运行起来)
    • 与静态库的比较:
      • 由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码体积会增大。动态库的代码只需要存在一份,其他程序通过函数地址使用,所以代码体积小。
      • 静态库发生变化后,新的代码需要重新链接嵌入到执行程序中。动态库发生变化后,如果库中函数的定义(或地址)未变化,其他使用DLL的程序不需重新链接。
  2. 动态库的创建
    • 建立项目
    • 添加库程序
    • 库程序导出 (导出函数偏移地址)- 提供给使用者库中的函数等信息。
  3. 动态库的使用
    • 隐式链接(使动态库执行起来的过程不需要程序员负责,过程不明显)
    • 显式链接(使动态库程序运行起来的过程需要程序员自己负责)
  4. 动态库的函数
    • 实现动态库的函数
    • 库函数的导出
      • 声明导出
        使用 _declspec(dllexport) 在函数定义前面,导出函数
        注意:动态库编译链接后,也会有LIB文件,是作为动态库函数映射使用,与静态库不完全相同。
      • 模块定义文件 .def
        例如:
           LIBRARY DLLFunc //库
           EXPORTS         //库导出表
           DLL_Mul      @1 //导出的函数
            DLL_Sub     @2
  5. 制作动态库
    • 声明到处:_declspec(dllexport)将函数的偏移地址导到了dll的文件头中,如果是C++编译器,dll文件头中记录的是换名之后的函数对应的偏移地址
      lib文件记录的仅仅是换名之后的函数名对应的编号
    • 模块定义文件到处:将函数的偏移地址导出到了dll的文件头中,即便C++编译器,dll文件头中记录的是为换名的函数名对应的偏移地址
      lib文件中记录的仅仅是未换名的函数名对应的编号
    • 使用动态库:
    • 隐式链接---操作系统的加载负责使动态库执行(动态库的首地址)
      链接器负责到lib文件中抓函数的编号,程序执行起来后操作
      系统加载器负责拿着编号到dll文件中查询函数的偏移地址
    • 显示链接---程序员调用LoadLibrary使动态库执行
      程序员调用GetProcAddress()函数,在这个函数内部通过函
      数名称到dll文件头中查询函数的偏移地址
      例如:GetProcAddress(hDll, “CPPdll_add”);
  6. 库函数的使用
    1. 隐式链接
      • 头文件和函数原型
        可以在函数原型的定义前,增加declspec(dllimport), 例如
        _declspec(dllimport) int DLL_Add( ... );
        如果库函数使用C格式导出,需要在函数定义增加 extern “C”
      • 导入动态库的LIB文件
      • 在程序中使用函数
      • 隐式链接的情况,DLL可以存放的路径:
        (1)与执行文件中同一个目录下-----推荐使用
        (2)当前工作目录
        (3)Windows目录
        (4)Windows/System32目录
        (5)Windows/System
        (6)环境变量PATH指定目录
        注意:高版本VC的配置文件
    2. 显式链接
      • 定义函数指针类型 typedef
      • 加载动态库
      HMODULE LoadLibrary(
      LPCTSTR lpFileName  //动态库文件名(.exe与.dll文件在同一路径下)或全路径
      ); 返回DLL的实例句柄(HMODULE 实际就是HINSTANCE)
      • 获取函数地址
      FARPROC GetProcAddress(
      HMODULE hModule,    //DLL句柄
      LPCSTR lpProcName   //函数名称
      ); 成功返回函数的绝对地址   返回地址DLL_ADD
      • 使用函数
      • 卸载动态库
      BOOL FreeLibrary(
      HMODULE hModule   //DLL的实例句柄
      );
    3. 两种链接方式对比
      • 在库函数的定义不变情况下:
        隐式链接,由于库函数地址是在程序编译链接时设置,所以当动态库变化后,使用程序需要重新编译链接。
        显式链接,由于库函数地址是在程序执行时,动态的从库中查询,所以库变化后,不需要重新编译链接。
      • 动态库加载
        隐式链接,动态库是在程序启动时就被加载,当DLL不存在,程序无法启动
        显式链接,动态库只在使用LoadLibrary函数,才会被加载。
  7. DLL中类的使用
    • DLL中类的导出
      在类名称前增加 _declspec(dllexport) 定义,例如:
      class _declspec(dllexport) CMath {};实际上是导出类的成员函数的函数名
      通常使用预编译开关切换类的导入导出定义,例如:
        #ifdef DLLCLASS_EXPORTS
        #define EXT_CLASS _declspec(dllexport)//DLL
        #else
        #define EXT_CLASS _declspec(dllimport)//使用者
        #endif
        class EXT_CLASS CMath{
    • 使用DLL中的类
      * 导入DLL的LIb
      * 类的定义 CMath math;
      * 使用类 math.Add(…);
    • 动态库的程序入口
      入口程序不是DLL必须的。常用于DLL内部初始化或善后处理。
      BOOL WINAPI DllMain( HINSTANCE hinstDLL, //动态库实例句柄 DWORD fdwReason, //被调用的原因 LPVOID lpvReserved //保留值 ); 返回TRUE,表示动态库加载成功。
      动态库的加载或卸载时会被调用。例如:使用LoadLibrary或FreeLibrary时会被调用。

    • DLLMAIN动态库入库函数
    BOOL WINAPI DllMain(  
    HINSTANCE hinstDLL,  // handle to the DLL module
      DWORD fdwReason,  // reason for calling function
      LPVOID lpvReserved   // reserved
    );

windows文件

  1. 创建或打开Windows文件
    HANDLE CreateFile( LPCTSTR lpFileName, //文件名称(带盘符的全路径名) DWORD dwDesiredAccess, //访问权限 DWORD dwShareMode, //共享方式,读共享,即可以同时多个程序读,也可以允许别人删除,写等方式 LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性,默认为NULL,windows下该属性基本都为NULL DWORD dwCreationDisposition, //创建或打开方式 DWORD dwFlagsAndAttributes, //文件属性 HANDLE hTemplateFile //文件句柄模板,默认为NULL,即为全双工 );
    该函数既可以操作硬盘文件,也可以操作外围设备,如打印机
    成功返回文件句柄。相当于Unix中的文件描述符

    DWORD dwShareMode,  //共享方式,读共享,即可以同时多个程序读,也可以允许别人删除,写等方式
    FILE_SHARE_DELETE---质询方式
    FILE_SHARE_READ---读共享
    FILE_SHARE_WRITE---写共享
    DWORD dwCreationDisposition,  //创建或打开方式
    CREATE_NEW---没有则新建,有则失败
    CREATE_ALWAYS---没有则新建,有则先删除再新建
    OPEN_EXISTING---有就打开,没有就失败
    OPEN_ALWAYS---有就打开,没有就创建然后再打开
    TRUNCATE_EXISTING---打开文件的同时,清空文件
  2. 写数据
    BOOL WriteFile( HANDLE hFile, //文件句柄 LPCVOID lpBuffer, //数据BUFF DWORD nNumberOfBytesToWrite, //数据长度 LPDWORD lpNumberOfBytesWritten, //返回实际写入的数据长度 LPOVERLAPPED lpOverlapped //默认为NULL );

  3. 读数据
    BOOL ReadFile( HANDLE hFile, //文件句柄 LPVOID lpBuffer, //数据BUFF DWORD nNumberOfBytesToRead, //要读的字节数 LPDWORD lpNumberOfBytesRead, //实际读到字节数 LPOVERLAPPED lpOverlapped //默认为NULL );

  4. 关闭文件
    BOOL CloseHandle( HANDLE hObject //文件句柄 );
  5. 文件长度
    DWORD GetFileSize( HANDLE hFile, //文件句柄 LPDWORD lpFileSizeHigh //返回文件长度的高32位 ); 返回值是文件长度的低32位
    DWOED就是无符号long类型,主要是为了方便存储大文件,函数返回值是以字节为单位,第二个参数以G为单位

  6. 文件指针
    DWORD SetFilePointer( HANDLE hFile, //文件句柄 LONG lDistanceToMove, //偏移量的低32位 PLONG lpDistanceToMoveHigh, //偏移量的高32位 DWORD dwMoveMethod//偏移的相对位置 );

    DWORD dwMoveMethod//偏移的相对位置
    FILE_BEGIN
    FILE_CURRENT
    FILE_END

    SetFilePointer函数返回实际偏移量的低32位,lpDistanceToMoveHigh返回实际偏移量的高32位

  7. 文件相关操作
    CopyFile - 拷贝文件
    DeleteFile - 删除文件
    MoveFile - 移动文件

  • 文件遍历
    1. 查找文件
    HANDLE FindFirstFile(
      LPCTSTR lpFileName, //查找路径
      LPWIN32_FIND_DATA lpFindFileData  //查找的数据
    );  返回查找句柄
    1. 获取下一个文件
    BOOL FindNextFile(
      HANDLE hFindFile, //查找句柄
      LPWIN32_FIND_DATA lpFindFileData //查找的数据
    ); 找到返回TRUE
    1. 关闭查找
    BOOL FindClose(
        HANDLE hFindFile   //查找句柄
      );
文件操作实例
```
// WinFile.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
HANDLE hd;
void Create()
{

    hd=CreateFile(_T("d:/file.txt"),GENERIC_WRITE,
            FILE_SHARE_READ,NULL,CREATE_NEW,
            FILE_ATTRIBUTE_NORMAL,NULL
        );
}

void Write()
{

    char szText[] = "hello file";
    DWORD nLen = 0;
    WriteFile(hd, szText, strlen(szText), &nLen, NULL);
    printf("准备写入:%d,实际写入:%d\n", strlen(szText), nLen);
    //CloseHandle(hd);
}

void Read()
{
    char szText[256] = { 0 };
    DWORD nLen = 0;
    DWORD nHeigth = 0;
    DWORD nLow=GetFileSize(hd, &nHeigth);
    ReadFile(hd, szText, nLow, &nLen, NULL);
    printf("数据:%s,准备读取:%d,实际读取:%d\n",szText, nLow,nLen);

    CloseHandle(hd);

}

int main(int argc,char * argv[])
{
    Create();
    Write();
    Read();
    system("pause");
    return 0;
}
```

转载于:https://www.cnblogs.com/lhfen/p/6032851.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值