Win32_Windows库

一 Windows的库

  由于项目的复杂程序或为了提高代码的重用率,所以才引入了库程序

  库包含两种:
  1 静态库:扩展名为 lib 的文件,是不能被加载的程序,可以理解为目标程序的归档。
  2 动态库:扩展名是 dll 的文件,是可以被应用程序加载的程序

二 静态库

  1 静态库的特点
    1.1 目标程序的归档
    1.2 静态库的代码会被嵌入到程序当中,程序执行时不需要静态库的存在

  2 C语言静态库
    2.1 创建静态库
      创建Win32静态库项目使用 *.c 文件建立项目
    2.2 添加静态库函数
    2.3 在程序中将静态库导入
      1)项目的 setting 设置
      2)使用关键字 pragma
      #pragma comment(lib,"../lib/winclib.lib");
    2.4 使用静态库提供的函数
      在C语言程序中,直接使用函数即可

生成winclib.lib文件
 1 //winclib.lib
 2 
 3 int C_Add(int nAdd1,int nAdd2)
 4 {
 5     return(nAdd1 + nAdd2);
 6 }
 7 
 8 int C_Sub(int nSub1,int nSub2)
 9 {
10     return(nSub1 - nSub2);
11 }
调用winclib.lib
 1 //useclib.c
 2 
 3 #pragma comment(lib,"../lib/winclib.lib")//导入静态库
 4 
 5 int main()
 6 {
 7     int nAdd = 0;
 8     int nSub = 0;
 9     //使用C静态库函数
10     nAdd = C_Add(100,100);
11     nSub = C_Sub(100,100);
12 
13     printf("ADD:%d\n",nAdd);
14     printf("SUB:%d\n",nSub);
15     return 0;
16 }

   3 c++ 语言的静态库
    3.1 创建静态库
      创建win32静态库项目,使用 *.CPP文件建立项目
    3.2 添加静态库的函数
    3.3 导入静态库
      1)项目的 Setting 里设置
      2)使用关键字 pragma
      #pragma comment(lib,"../lib/wincpplib.lib")
    3.4 定义库函数的原形
      int CPP_Add(int nAdd1,int nAdd2);
    3.5 使用库函数
    注:如果在CPP文件使用C语言静态库,定义静态库函数原型需要增加 extern"C".
    如:extern "C" int C_Add(int nAdd1,int nAdd2);

Wincpplib.cpp
1 int CPP_Add(int nAdd1,int nAdd2)
2 {
3     return(nAdd1 + nAdd2);
4 }
5 
6 int CPP_Sub(int nSub1,int nSub2)
7 {
8     return(nSub1 - nSub2);
9 }
View Code
 1 // usecpplib.cpp : Defines the entry point for the console application.
 2 //使用.lib
 3 
 4 #include "stdafx.h"
 5 
 6 #pragma comment(lib,"../lib/wincpplib.lib")//导入C++的静态库
 7 #pragma comment(lib,"../lib/winclib.lib")
 8 //定义函数原形
 9 int CPP_Add(int nAdd1,int nAdd2);
10 int CPP_Sub(int nSub1,int nSub2);
11 
12 //加载C定义的lib库格式
13 extern "C" int C_Add(int nAdd1,int nAdd2);
14 extern "C" int C_Sub(int nSub1,int nSub2);
15 
16 int main(int argc, char* argv[])
17 {
18     //使用C++库函数
19     int nAdd = CPP_Add(100,100);
20     int nSub = CPP_Sub(100,100);
21     printf("ADD:%d\n",nAdd);
22     printf("SUB:%d\n",nSub);
23     //使用C库函数
24     int nAdd2 = C_Add(100,100);
25     int nSub2 = C_Sub(100,100);
26     printf("C_ADD:%d\n",nAdd);
27     printf("C_SUB:%d\n",nSub);
28     return 0;
29 }

三 动态库
  1 动太库的好处
    1.1 可以提供模块化的方式,方便协调开发
    1.2 对源代码保护
    1.3 减小可执行文件的大小
    1.4 提供代码的重用率等

  2 动态库的基本使用方法
    2.1 动态库的创建
    2.2 加载动态库
    2.3 获取并使用库函数、变量或类
    2.4 释放动态库

  3 动态库的函数
    3.1 创建
      1)创建DLL的项目
        使用Win32 DLL 项目创建DLL,添加相应的文件
      2) 增加动态库函数
      3) 导出动态库函数
       (1)使用 _declspec(dllexport)方式在函数前增加这个个关键字,如:
           _declspec(dllexport) int Dll_Add()
       (2)增加 extern "C"方式,即:extern "C"_declspec(dllexport)以
          C语言方式导出函数
       (3)使用DEF文件导出
          增加扩展名为DEF的文件到项目中,在DEF文件中添加导出定义
          LIBRARY dllfunc.dll  //导出库
          EXPORTS       //导出表
            Dll_Mul @1    //导出函数
            Dll_Div @2
    3.2 使用
      1)隐式链接
        (1) 导入LIB
          项目的 Setting 或者使用 #pragma 导入,如:
            #pragma comment(lib,"../lib/dllfunc.lib")
        (2) 定义函数原形
          声明了一个和导出函数一致函数定义,如果DLL采用 extern "C"导出函数
            需要定义 extern "C" 方式函数原形
        (3) 使用函数
          直接使用函数即可
        (4)应用程序查找DLL的路径
          查找当前应用程序的目录
          当前的工作目录
          查找 Windows System32的目录
          查找 Windows System的目录
          查找 Windows 目录
          查找环境变量PATH 指定路径

View Code
 1 // 生成dllfunc.dll文件
 2 // C++导出方式
 3 _declspec(dllexport) int Dll_Add(int nAdd1,int nAdd2)
 4 {
 5     return(nAdd1 + nAdd2);
 6 }
 7 // C导出方式
 8 extern "C" _declspec(dllexport) int Dll_Sub(int nSub1,int nSub2)
 9 {
10     return(nSub1 - nSub2);
11 }
12 // DEF导出方式
13 int Dll_Mul(int nMul1,int nMul2)
14 {
15     return(nMul1 * nMul2);
16 }
dllfunc.def文件
1 LIBRARY DllFunc.dll
2 EXPORTS
3     Dll_Mul @1
View Code
 1 // callDllfun.cpp : Defines the entry point for the console application.
 2 //使用
 3 
 4 #include "stdafx.h"
 5 
 6 #pragma comment(lib,"../lib/DllFunc.lib")//导入DLL的Lib文件
 7 // 定义函数原形
 8 int Dll_Add(int nAdd1,int nAdd2);
 9 extern "C" int Dll_Sub(int nSub1,int nSub2);
10 int Dll_Mul(int nMul1,int nMul2);
11 
12 int main(int argc, char* argv[])
13 {
14     //使用函数
15     int nAdd = Dll_Add(100,100);
16     int nSub = Dll_Sub(100,100);
17     int nMul = Dll_Mul(100,100);
18     printf("Dll_Add:%d\n",nAdd);
19     printf("Dll_Sub:%d\n",nSub);
20     printf("Dll_Mul:%d\n",nMul);
21     return 0;
22 }

     2)显示链接
      (1)加载动态库

HINSTANCE LoadLibrary(
  LPCTSTR lpLibFileName);//DLL的路径

     返回加载好DLL的句柄
      (2)定义函数原形对应 的函数指针
      (3)获取函数地址

FARPROC GetProcAddress(
              HMODULE hModule,//DLL的句柄
              LPCSTR lpProcName//函数的名称
             );

     返回对应函数地址
     注意:
        1 对于 _declspec(dllexport)导出的函数由于函数名称发现变化,所以无
          法使用函数名称获取对应的函数地址,尽量采用隐式链接方式
        2 extern "C" 或DEF方式导出的函数可以正常的使用函数名称获取函数地址
          
      (4)使用函数
      (5)释放函数
         FreeLibrary

View Code
 1 // InvokeDllFunc.cpp : Defines the entry point for the console application.
 2 //
 3 
 4 #include "stdafx.h"
 5 #include "windows.h"
 6 
 7 typedef int (* DLL_ADD)(int nAdd1,int nAdd2);
 8 typedef int (* DLL_SUB)(int nSub1,int nSub2);
 9 typedef int (* DLL_MUL)(int nMul1,int nMul2);
10 
11 void UseDll()
12 {
13     //加载动态库
14     HMODULE hDll =  (HMODULE)LoadLibrary("dllfunc.dll");
15     if (hDll == NULL)
16     {
17         printf("Load Failed\n");
18         return;
19     }
20 
21     // 定义函数指针
22 
23     DLL_ADD Dll_Add = NULL;
24     DLL_SUB Dll_Sub = NULL;
25     DLL_MUL Dll_Mul = NULL;
26 
27     //获取函数地址
28     Dll_Add = (DLL_ADD) GetProcAddress(hDll,"Dll_Add");
29     if (NULL == Dll_Add)
30     {
31         printf("Get Dll_Add Failed\n");
32     }
33     printf("Dll_Add:%p\n",Dll_Add);
34     Dll_Sub = (DLL_SUB) GetProcAddress(hDll,"Dll_Sub");
35     if (NULL == Dll_Sub)
36     {
37         printf("Get Dll_Sub Failed\n");
38     }
39     printf("Dll_Sub:%p\n",Dll_Sub);
40     Dll_Mul = (DLL_MUL) GetProcAddress(hDll,"Dll_Mul");
41     if (NULL == Dll_Mul)
42     {
43         printf("Get Dll_Mul Failed\n");
44     }
45     printf("Dll_Mul:%p\n",Dll_Mul);
46     //使用函数
47     int nSub = Dll_Sub(100,100);
48     int nMul = Dll_Mul(100,100);
49     printf("Dll_Sub:%d\n",nSub);
50     printf("Dll_Mul:%d\n",nMul);
51 
52     //释放动态库
53     FreeLibrary(hDll);
54 }
55 
56 int main(int argc, char* argv[])
57 {
58     UseDll();
59     return 0;
60 }

  4 动态库的变量
    4.1 定义全局变量
    4.2 导出全局变量
      4.2.1 _declspec(dllexport)导出
      _declspec(dllexport) int g_nValuel = 100;
      4.2.2 DEF文件导出
        int g_nValue2 = 200;
        在DEF文件的导出列表中增加 g_nValue2 @1 DATA
    4.3 导入LIB文件
    4.4 定义导入变量
      需要使用 _declspec(dllimport) 定义变更
    4.4 使用变量

1 /*******************************************
2 *
3 * dllvalue.cpp
4 ********************************************/
5 //导出DLL的全局变量
6 _declspec(dllexport) int g_nValuel = 100;
7 
8 // DEF 导出的全局变量
9 int g_nValue2 = 200;
dllvalue.def
1 LIBRARY dllvalue
2 EXPORTS
3     g_nValue2 @1 DATA
usevalue.cpp
 1 // usevalue.cpp : Defines the entry point for the console application.
 2 //
 3 
 4 #include "stdafx.h"
 5 
 6 #pragma comment(lib,"../lib/dllvalue.lib")//导入LIB
 7 
 8 extern _declspec(dllimport) int g_nValuel;//定义DLL导入变量
 9 extern _declspec(dllimport) int g_nValue2;
10 
11 int main(int argc, char* argv[])
12 {
13     printf("g_nValuel = %d\n",g_nValuel);
14     printf("g_nValue2 = %d\n",g_nValue2);
15     return 0;
16 }

  5 动态库的类
    5.1 创建动态库并定义类
    5.2 从DLL中导出类
      在类名称前增加 _declspec(dllexport)定义
      class _declspec(dllimport) CMath
        {...};
    5.3 使用时导入LIB文件
    5.4 导入
    5.5 使用类  

math.h
 1 //math.h
 2 #ifndef _MATH_H_
 3 #define _MATH_H_
 4 
 5 //定义类导入导出宏
 6 #ifdef _DLLCLASS_DLL_    //(在设置   C/C++  Category--Preprocessor 下  增加_DLLCLASS_DLL_)
 7 #define DLLCLASS_EXT __declspec(dllexport)
 8 #else
 9 #define DLLCLASS_EXT __declspec(dllimport)
10 #endif //_DLLCLASS_DLL_
11 
12 //增加类的导入导出宏
13 class DLLCLASS_EXT CMath 
14 {
15 public:
16     int Add( int nAdd1, int nAdd2 );
17     int Sub( int nSub1, int nSub2 );
18 };
19 
20 #endif //_MATH_H_
math.cpp
 1 //math.cpp
 2 #include "math.h"
 3 
 4 int CMath::Add( int nAdd1, int nAdd2 )
 5 {
 6     return ( nAdd1 + nAdd2 );
 7 }
 8 
 9 int CMath::Sub( int nSub1, int nSub2 )
10 {
11     return ( nSub1 - nSub2 );
12 }

  

View Code
 1 #include "stdafx.h"
 2 //导入DLL的LIB文件
 3 #pragma comment( lib, "../lib/dllclass.lib")
 4 //需要类的导入方式的声明
 5 #include "../DllClass/math.h"
 6 
 7 int main(int argc, char* argv[])
 8 {    //使用DLL中的类
 9     CMath math;
10     int nAdd = math.Add( 100, 100 );
11     int nSub = math.Sub( 100, 100 );
12     printf("math.Add = %d\n", nAdd );
13     printf("math.Sub = %d\n", nSub );
14     return 0;
15 }

 

     5.6 关于类的导入和导出
      1)定义一个宏,例如:
        #ifdef _DLLCLASS_DLL_
        #define DLLCLASS_EXT _declspec(dllexport)
        #else
        #define DLLCLASS_EXT _declspec(dllimport)
        #endif //_DLLCLASS_DLL
      2)根据编译项目,修改_DLLCLASS_DLL_宏声明对于导出类,需要定义
        _DLLCLASS_DLL_,否则不需要定义 _DLLCLASS_DLL_ 宏
      3)类的定义为:
        class DLLCLASS_EXT CMath
          {...};
  6 DllMain 函数
    是DLL文件入口函数。当程序加载或者释放动态库的时候会自动调用这个函数

BOOL WINAPI DllMain(
            HINSTANCE hinstDLL,//DLL的句柄
            DWORD fdwReason,//DLL被调用 的原因
            LPVOID lpvReserved //保留值
            );

  fdwReason -
        DLL_PROCESS_ATTACH 进程加载
        DLL_THREAD_ATTACH   进程加载
        DLL_THREAD_DETACH   进程卸载
        DLL_THREAD_DETACH   进程卸载
    返回值表示是否加载成功

View Code
 1 #include "windows.h"
 2 #include "stdio.h"
 3 
 4 BOOL WINAPI DllMain( HINSTANCE hinstDLL,
 5     DWORD fdwReason, LPVOID lpvReserved )
 6 {
 7     printf( "DLL=%p, Reason=", hinstDLL );
 8     switch( fdwReason )
 9     {
10     case DLL_PROCESS_ATTACH:
11         printf( "DLL_PROCESS_ATTACH\n" );
12         break;
13     case DLL_THREAD_ATTACH:
14         printf( "DLL_THREAD_ATTACH\n" );
15         break;
16     case DLL_THREAD_DETACH:
17         printf( "DLL_THREAD_DETACH\n" );
18         break;
19     case DLL_PROCESS_DETACH:
20         printf( "DLL_PROCESS_DETACH\n" );
21         break;
22     }
23     return TRUE;
24 }
25 
26 //C++导出方式
27 __declspec(dllexport) int Dll_Add( int nAdd1, int nAdd2 )
28 {
29     return ( nAdd1 + nAdd2 );
30 }
31 //C的导出方式
32 extern "C" __declspec(dllexport) int Dll_Sub( int nSub1, int nSub2 )
33 {
34     return ( nSub1 - nSub2 );
35 }
36 //DEF的导出方式
37 int Dll_Mul( int nMul1, int nMul2 )
38 {
39     return ( nMul1 * nMul2 );
40 } 

 

posted @ 2012-10-16 09:18  吟唱黑暗  阅读(324)  评论(0编辑  收藏  举报