zoukankan      html  css  js  c++  java
  • lib库dll库的使用方法与关系

    一、lib库

      lib库有两种:一种是静态lib(static Lib),也就是最常见的lib库,在编译时直接将代码加入程序当中。静态lib中,一个lib文件实际上是任意个obj文件的集合,obj文件是cpp文件编译生成的。

            另一种lib包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供。也就是平时编写dll时附带产生的lib,其中Lib只是Dll的附带品,是DLL导出的函数列表文件而已。

      共同点:两者都是二进制文件,都是在链接时调用,使用static lib的exe可以直接运行,使用另一种lib的exe需要对应的dll才能运行。

      静态lib库的创建示例:

      1.VS2005(包含)以上的版本

      2.建立win32控制台工程

      3.下一步选择static library

      4.完成

      代码:

     1 //mylib.h
     2 #ifndef MYLIB_H_H
     3 #define MYLIB_H_H
     4 #include "stdafx.h"
     5 
     6 void display();
     7 void display1();
     8 void display2();
     9 
    10 #define A(x)  (x)*(x)
    11 
    12 #endif

      

     1 //mylib.cpp
     2 #include "stdafx.h"
     3 #include "mylib.h"
     4 
     5 void display()
     6 {
     7     cout<<"This is display"<<endl;
     8 }
     9 
    10 void display1()
    11 {
    12     cout<<"This is display1"<<endl;
    13 }
    14 
    15 void display2()
    16 {
    17     cout<<"This is display2"<<endl;
    18 }

    编译之后生成一个mylib.lib的库文件,引用库文件如下:

       右击工程-->属性(alt+F7)-->C/C++-->附加包含目录--->包含所需要的头文件。

       右击工程-->属性(alt+F7)-->链接器-->常规--->附加目录--->包含lib库所在的目录

       右击工程-->属性(alt+F7)-->输入--->附加依赖项--->lib库名

    这样就能引用该lib内的函数了

      

     1 #include "stdafx.h"
     2 #include "mylib.h"
     3 
     4 int _tmain(int argc, _TCHAR* argv[])
     5 {
     6     display();
     7     display1();
     8     display2();
     9     cout<<A(6-2)<<endl;
    10     getchar();
    11     return 0;
    12 }

    当然,还可以使用#pragma comment(lib, "LibPath")的方法来调用Lib文件,同时必须包含相应的头文件。

      另一种lib库的使用方法:用法静态库一致,唯一不同的区别是运行时要加上相应的dll。

      DLL的用法:

      dll其实和exe是几乎完全一样的,唯一的不一样就是Exe的入口函数式WinMain函数(控制台程序是main函数),而Dll是DllMain函数,其他完全是一样的。所以有人也戏称dll是不能自己运行的exe。dll的创建也比较简单唯一麻烦的就是要定义导出函数接口。

      dll的创建过程:

      建立win32控制台工程,在应用程序设置的步骤,选择”动态库 Dynamic Library”,完成即可。(这里只是针对最简单的Dll,Win32 Application的方式稍有不同)

      定义导出函数接口的方法有两种:

      1.使用__declspce宏

      

     1 // dllmain.cpp : 定义 DLL 应用程序的入口点。
     2 #include "stdafx.h"
     3 
     4 BOOL APIENTRY DllMain( HMODULE hModule,
     5                        DWORD  ul_reason_for_call,
     6                        LPVOID lpReserved
     7                      )
     8 {
     9     switch (ul_reason_for_call)
    10     {
    11     case DLL_PROCESS_ATTACH:
    12     case DLL_THREAD_ATTACH:
    13     case DLL_THREAD_DETACH:
    14     case DLL_PROCESS_DETACH:
    15         break;
    16     }
    17     return TRUE;
    18 }
    View Code
     1 //mydll1.h
     2 
     3 #ifndef MYDLL_H_H
     4 #define MYDLL_H_H
     5 
     6 extern "C" __declspec(dllexport) void display(void);
     7 extern "C" __declspec(dllexport) void display1(void);
     8                                  void display2(void);
     9 
    10 #endif
    View Code
     1 //mydll1.cpp
     2 #include "stdafx.h"
     3 #include "mydll1.h"
     4 
     5 void display(void)
     6 {
     7     cout<<"call display()"<<endl;
     8 }
     9 
    10 void display1(void)
    11 {
    12     cout<<"call display1()"<<endl;
    13 }
    14 
    15 void display2(void)
    16 {
    17     cout<<"call display2()"<<endl;
    18 }
    View Code

      mydll1.h头文件中的:

      

    1 extern "C" __declspec(dllexport) void display(void);

      这里的extern "C" 表示我们要按照C语言的方式编译该函数,防止在C++工程中编译出现函数名错误,因为C中没有重载而C++中允许重载,所以C++中函数编译后会出现display@1的形式;让编译器以C语言的编译方式编译可以保证C可以调用C++的动态链接库。__declspec(dllexport)表示下来的函数是dll的导出函数接口。没有导出的接口是不可使用的,这里和静态lib库有所区别,静态lib库中的所有函数、宏定义等都是可以使用的。

      2.使用def文件,该文件的功能类似于__declspec(dllexport)的功能。

      在资源文件目下添加def文件:

      

    LIBRARY
    EXPORTS
        display
        display1

      dll的调用:

      1.dll的显示调用:前提是我们必须知道函数名、返回值、参数列表。此时不需要相应的头文件,也不需要lib文件。只需要对应的dll就可以了。

      

     1 // test_my_dll.cpp : 定义控制台应用程序的入口点。
     2 //
     3 
     4 #include "stdafx.h"
     5 #include "windows.h"
     6 
     7 
     8 int _tmain(int argc, _TCHAR* argv[])
     9 {
    10     HINSTANCE hInstance = LoadLibrary("mydll1.dll");
    11     typedef void(*_print)(void);
    12     _print printFun;
    13     if(hInstance != NULL)
    14     {
    15         printFun = (_print)GetProcAddress(hInstance,"display1");
    16     }
    17     printFun();
    18     FreeLibrary(hInstance);
    19     system("pause");
    20     return 0;
    21 }

      这种情况下:HINSTANCE hInstance = LoadLibrary("mydll1.dll");会出现”2 IntelliSense: "const char *" 类型的实参与 "LPCWSTR" 类型的形参不兼容 “问题。解决办法:工程--->属性--->常规-->字符集--->使用多字节字符集就可以了。

      2.dll的隐式调用

       这是相应的lib库就派上用场了,其用法static library用法一致。

    总结:显示调用和隐式调用这两种方法各有千秋,显示调用优点是只要接口参数列表没有发生改变,修改了函数实现的细节也没关系,所调用的exe程序不用重新编译只需替换新版的dll就可以。在大的项目中只用比较方便,但调用过程相对复杂需要使用一系列的windows函数还有函数指针等。对于隐式调用和static library用法一致比较容易理解,缺点是只要修改了任意内容相应的exe都需要重新编译。

    参考资料:

        http://www.cppfans.org/1394.html

        http://blog.csdn.net/qq419036154/article/details/6438539

        http://blog.csdn.net/tianhen791/article/details/7209740

  • 相关阅读:
    PHP加速器eAccelerator安装
    WCF
    WCF
    WCF
    前端学习书籍推荐
    问题集录01--java对list列表进行排序
    基础知识:字符编码
    基础知识:if条件、while循环、for循环 相关练习
    基础知识:语言、编程、计算机组成、cpu、存储器
    视图 索引 存储过程
  • 原文地址:https://www.cnblogs.com/maxiaofang/p/4303306.html
Copyright © 2011-2022 走看看