VC ++链接库(三)非MFC动态库

来源:互联网 发布:centos安装内核开发包 编辑:程序博客网 时间:2024/05/22 06:16

    非MFC动态库指的是不用MFC的类库结构,直接用C语言写的DLL,其导出的函数是标准的C接口,能被非MFC或MFC编写的应用程序所调用

     在VC++6.0中,File-->New-->Win32 Dynamic-Link Library创建非MFC动态库

(一)一个简单的非MFC动态库                                                           


    在VC++中new一个Win32 Dynamic-Link Library工程DllTest。注意不要选择MFC AppWizard(dll),因为用MFC AppWizard(dll)建立的将是后面要讲述的MFC 动态链接库。 
 
    在建立的工程中添加DllTest.h及DllTest.cpp文件,源代码如下:
//DllTest.h文件#ifdef DLL_API#else#define DLL_API extern "C" _declspec(dllimport) // 需要在每个要导出的函数前面添加标示符 _declspec(dllimport)                                                                         //用DLL_API代替_declspec(dllimport)                                                                      //一般添加 extern "C"解决名字改编问题#endifDLL_API int add(int a,int b);DLL_API int subtract(int a,int b);

//DllTest.cpp文件#define DLL_API extern "C" _declspec(dllexport)   //这里是_declspec(dllexport) #include "DllTest.h"#include <Windows.h>#include <stdio.h>int add(int a,int b){     return a+b;}int subtract(int a,int b){     return a-b;}
直接编译就产生了.lib .dll文件

(二)隐式链接的方式加载DLL                                                           

      再新建一个工程Test(我们随便建一个win32 console Application),该工程只有一个Test.cpp文件它调用DLL中的函数,代码如下:
#include <stdio.h>  #include "..\DllTest\DllTest.h"//#pragma comment( lib, "..\\DllTest\\Debug\\DllTest.lib" )  int main(int argc, char *argv[])  {           printf("%d\n",add(5,3));     return 0;  }  
如何隐式加载,下面我们一步步的分析,
       直接build会出错  Test.obj : error LNK2001: unresolved external symbol __imp__add,,有链接的时候出错,解决:在Test程序中,选择Project-->Settings-->ling-->Object/library modules中输入DllTest.lib(或者在程序中加#pragma comment( lib, "..\\DllTest\\Debug\\DllTest.lib" ) ),然后选择tools-->options-->directories-->library files菜单或选项,填入库文件路径E:\Program Files\Microsoft Visual Studio 6.0\MyProjects\DllTest\Debug(或者直接将产生的DllTest.lib文件拷贝到Test工程下),重新build没有问题了。
      运行,出错提示计算机中丢失DllTest.dll,那么我们就需要将产生的DllTest.dll文件拷贝到Test工程目录下,重新运行成功
                              


(三)声明导出函数                                                                        

      在刚才的例子中给出的是在函数声明前面加上_declspec(dllimport),同时在前面加上了extern "C"
           注:1.编译器在生成DLL时,会对导出的函数进行名字改编,使用不同的编译器分别生成DLL和访问该DLL的客户端程序的话,后者在访问该DLL的导出函数时就会出现问题,所以一般在定义导出函数时,加上限定符extern "C"
                 2.使用extern "C"可以解决C++和C语言之间互相调用时函数命令的问题,但是不能用于导出一个类的成员函数,只能用于导出全局函数这种情况
                 3.如果函数的调用约定发生了改变,即使使用了extern "C",它们的名字仍然会发生改变,那么就有了第二周声明导出函数的方式,使用模块文件(DEF)
       接着我们将声明导出函数的另外一种方法,使用模块文件

      下面我们重新建Win32 Dynamic-Link Library工程DllTest,添加DllTest.cpp文件,代码如下:
int add(int a,int b){     return a+b;}int subtract(int a,int b){     return a-b;}
 
      然后添加模块定义文件DllTest.def,我们可以在DllTest工程目录下新建一个空的文本取名DllTest.def,然后在[Project\Add To Project\Files...]-->Insert Files into Project,选择DllTest.def文件将其添加进Test工程,然后添加代码:
LIBRARY DllTest//LIBRARY指定动态链接库的内部名称,这个必须要和生成的动态链接库名称匹配EXPORTS//指明DLL要导出的函数addsubtractbuild 这个DllTest工程,就产生了.lib .dll文件

自己再编译一个测试工程,代码如下:
#include <stdio.h>  #include <windows.h> //typedef int(*lpAddFun)(int, int); // 宏定义函数指针类型int add(int a, int b);int subtract(int a , int b);int main(int argc, char *argv[]) {         printf( "%d\n" ,add(5,3));        printf( "%d\n" ,subtract(5,3));    return 0;  } 
要像刚才隐式加载一样的去做,才能运行成功

(四)显示加载DLL                                                                                 

       上面使用的都是隐式加载DLL的方法,对动态链接库的访问还可以使用显示加载方式:完全由编程者用API函数加载和卸载DLL,程序员可以决定 DLL 文件何时加载或不加载,显式链接在运行时决定加载哪个DLL文件

   第一步还是创建DllTest工程,产生.lib .dll文件,
   第二步新建工程Test(我们随便建一个win32 console Application),代码如下:
//Test.cpp#include <stdio.h>#include <Windows.h>typedef int (*ADDPROC)(int ,int );//定义函数指针类型int main(int argc,char *argv[]){     HINSTANCE hInst;     ADDPROC Add;     hInst=LoadLibrary("..\\DllTest\\Debug\\DllTest.dll");  //动态加载DLL     if(hInst!=NULL)     {          Add=(ADDPROC)GetProcAddress(hInst,"add");//获取DLL的导出函数          if(Add!=NULL)          {               int result=Add(5,3);               printf("%d\n",result);          }          FreeLibrary(hInst);     }     return 0;}





原创粉丝点击