Vc编写和调用Dll的简单例子

来源:互联网 发布:手机答题赚钱软件 编辑:程序博客网 时间:2024/05/17 07:37


用Visual Sudio 6.0新建一个工程,工程的类型选择Win32 Dynamic-Link Library.工程名任意

,其他所有选项取默认
新建一个cpp文件,代码如下:


[cpp] view plaincopy
01.int add(int a ,int b) 
02.{ 
03.      return a+b; 
04.} 
 
      如果工程类型是Win32 Console Application,那么在编译链接以后,会产生一个Debug目

录,并且里面有一个exe文件.
      这里我们的工程类型是Win32 Dynamic-Link Library,在编译链接以后,我们期望产生一

个Debug目录,并且里面有一个dll文件
    事实正是如此,我们可以用depends工具打开这个dll文件以查看它导出了什么函数depends

工具在Tools菜单下.实际上它是D:/Program Files/Microsoft Visual Studio/Common/Tools

下的一个文件.我们发现,这个dll没有导出任何东西.这是因为我们并没有说明我们要导出的东

西.在那个cpp里的函数并不是默认会被导出的.因为它们可能只是被我们要导出的函数的调用

的"内部函数".要导出一个函数,我们须要加上_declspec(dllexport),代码变为:
CODE:

[cpp] view plaincopy
01.int _declspec(dllexport) add(int a ,int b) 
02.{ 
03.       return a+b; 
04.} 
 

    再链接一次,再查看该dll文件,发现有一个?add@@YAHHH@Z的函数.好像很怪,不过总算看到

东西了.
现在来测试一下这个dll
新建一个工程,类型选Win32 Console Application
新建一个cpp文件,代码如下

CODE:

[cpp] view plaincopy
01.#include <iostream.h> 
02.#include <Windows.h> 
03.void main() 
04.{ 
05.      typedef int (*ADD)(int ,int);//函数指针类型 
06.      HINSTANCE Hint = ::LoadLibrary("DLL.dll");//加载我们刚才生成的dll 
07.      ADD add = (ADD)GetProcAddress(Hint,"add");//取得dll导出的add方法 
08.      cout<<add(3,4)<<endl; 
09.} 
 

     其中LoadLibrary都是Windows.h里面声明了的函数
编译链接,都没问题,运行.出错了!
     分析一下,程序怎么知道去哪里找我们的dll呢?
      它会按如下顺序搜索:当前可执行模块所在的目录,当前目录, Windows 系统目

录,Windows 目录。GetWindowsDirectory 函数检索此目录的路径,PATH 环境变量中列出的目

录。
所以我们要把我们的dll复制一份到这个测试工程的Debug目录之后,再运行
还是出错了!
    分析一下.我们刚才看到的是一个叫?add@@YAHHH@Z函数.那么,是不是这个原因呢?
把代码改为:

CODE:

[cpp] view plaincopy
01.#include <iostream.h> 
02.#include <Windows.h> 
03.void main() 
04.{ 
05.       typedef int (*ADD)(int ,int);//函数指针类型 
06.       HINSTANCE Hint = ::LoadLibrary("DLL.dll");//加载我们刚才生成的dll 
07.       ADD add = (ADD)GetProcAddress(Hint,"?add@@YAHHH@Z");//取得dll导出的add方法 
08.       cout<<add(3,4)<<endl; 
09.} 
 


     再编译链接,运行,成功了!那么怎么可以正确导出我们函数的名字呢?
     在生成dll的工程的代码加上extern "C",改为:

CODE:


[cpp] view plaincopy
01.extern "C" int _declspec(dllexport) add(int a ,int b) 
02.{ 
03.       return a+b; 
04.} 
 


编译链接后,查看dll文件,可以看到导出的函数变为add了,这时下面代码可以正常工作了
CODE:


[cpp] view plaincopy
01.#include <iostream.h> 
02.#include <Windows.h> 
03.void main() 
04.{ 
05.        typedef int (*ADD)(int ,int);//函数指针类型 
06.        HINSTANCE Hint = ::LoadLibrary("DLL.dll");//加载我们刚才生成的dll 
07.        ADD add = (ADD)GetProcAddress(Hint,"add");//取得dll导出的add方法 
08.        cout<<add(3,4)<<endl; 
09.} 
 
     除了用_declspec(dllexport)指明要导出的函数,用extern "C"来纠正名字,我们还可用

一个.def文件来达到以上目的
       在dll工程里新建一个文件,类型选Text File,在名字要带上后缀.def.内容如下:

[cpp] view plaincopy
01.LIBRARY 
02.EXPORTS 
03. add 
 

剩下的步骤就和之前一样了,用def文件还可以改变导出的函数的名字,例如
[cpp] view plaincopy
01.LIBRARY 
02.EXPORTS 
03. myadd = add 
 
使得导出的函数叫myadd,而不是add.还可以给函数指定一个序号
如:


[cpp] view plaincopy
01.LIBRARY 
02.EXPORTS  
03. myadd=add @4 
 

给myadd指定了一个序号
在测试工程里,可以根据序号取得我们的函数:

CODE:
[cpp] view plaincopy
01.#include <iostream.h> 
02.#include <Windows.h> 
03.void main() 
04.{ 
05.         typedef int (*ADD)(int,int); 
06.        HINSTANCE hInstance=::LoadLibrary("DLL.dll");  
07.        ADD add=(ADD)GetProcAddress(hInstance,MAKEINTRESOURCE(4));//根据序号取得函 
08. 
09.数 
10.        cout<<add(3,4)<<endl; 
11.        add=(ADD)GetProcAddress(hInstance,"myadd");//在def文件里指定的名字 
12.        cout<<add(3,4)<<endl; 
13.        FreeLibrary(hInstance);//释放加载了的dll文件占的资源 
14.} 
 


以上讲的是运行时静态加载dll,下面讲启动时动态加载dll
产生dll的工程不用变,还是上面这个(名字是myadd,序号为4)
测试代码改为:
//先把DLL.lib文件复制到本工程目录里


CODE:
[cpp] view plaincopy
01.#include <iostream.h> 
02.#pragma comment(lib,"DLL.lib") 
03.extern int myadd(int ,int );//没有加这句而只加上面这句(或在工程设置里加上DLL.lib)会链接错误 
04.void main() 
05.{ 
06.         cout<<myadd(3,4)<<endl; 
07.} 
 
#pragma comment(lib,"DLL.lib")指明了用到哪个dll,其中DLL.lib可以在Debug找到.我们也

要把DLL.lib复制到测试工程目录(不是Debug目录).我们也可以在工程属性里添加.方法是

Project--Settings--Link,在Object/libraries Modules最后加上 DLL.lib
extern int add(int ,int );指明了我们的add是一个外部函数,而不是在本文件定义的

      最后,强调一下,要把该复制的文件复制到正确的地方.当你产生的dll文件和我说的不一

致时,试一下选Build-Rebuild All

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米2a无限重启怎么办 红米3s像素好差怎么办 红米4x后摄像头进水了怎么办 红米手机卡死了又不能拆电池怎么办 红米1s格式化输入法没了怎么办 红米5a锁屏密码怎么办 红米1s手机开不开机怎么办 红米2a忘记解锁密码怎么办 红米手机忘了解锁图案怎么办 账户密码忘记了手机号不用了怎么办 手机电池用完了冲不进去电怎么办 华为手机电池一体的想扣电池怎么办 苹果微信支付显示需要验证码怎么办 天猫极速退货上门取件预约满怎么办 手机锁死了忘记魅族账号密码怎么办 魅蓝e升级系统开不了机了怎么办 京东第三方店铺显示关闭怎么办 派派怎么提现朋友不够怎么办 派派邀请30个好友才能提现怎么办 派派更换手机号后提现时怎么办 京东白条扫码支付被骗怎么办 实体店买的商品一天后降价怎么办 东西没收到确确认收货了怎么办 工行手机银行转农行卡号错了怎么办 发了后才知道顺丰快递到不了怎么办 三鹰之森吉卜力美术馆没票了怎么办 网贷平台借款如果还找你要钱怎么办 网贷要钱威胁成精神病怎么办 手机清除数据后忘了帐号密码怎么办 拼多多改了标题排名降了怎么办 16g的苹果手机内存不够怎么办 魅族手机没电关机充不进电怎么办 淘宝上买电器售后得不到处理怎么办 苏宁易购物流漏送货已签收怎么办 大件包裹快递快递员不送上楼怎么办 滴滴车主提现忘记登录密码怎么办 荣耀6玩游戏不卡但是闪退怎么办 qq扫码允许别人电脑登录怎么办 药店被举卖假药药检局没查到怎么办 苹果手机连接汽车点了不信任怎么办 装修的化妆品柜台与图纸不合怎么办