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

  • 相关阅读:
    iOS 苹果开发证书失效的解决方案(Failed to locate or generate matching signing assets)
    iOS NSArray数组过滤
    App Store2016年最新审核规则
    iOS 根据字符串数目,自定义Label等控件的高度
    iOS 证书Bug The identity used to sign the executable is no longer valid 解决方案
    Entity FrameWork 增删查改的本质
    EF容器---代理类对象
    Entity FrameWork 延迟加载本质(二)
    Entity FrameWork 延迟加载的本质(一)
    Entity FrameWork 增删查改
  • 原文地址:https://www.cnblogs.com/maxiaofang/p/4303306.html
Copyright © 2011-2022 走看看