五维思考

学习要加,骄傲要减,机会要乘,懒惰要除。 http://www.5dthink.cn

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1、 使用Visual C++ 6.0编写和链接DLL

打开Visual C++ 6.0集成开发环境,新建一个Win32 Dynamic-Link Library类型的工程CDLL,在工程中新建一个C语言源文件cdll.c。源文件中的内容如下:

__declspec(dllexport) int max(int x,int y) /* 比较两个整型变量大小的函数max */

{

   if (x>y)

      return x;

    else

      return y;

}

输入完毕后按下F7键来编译和链接CDLL.dll,之后可以在存放该工程的文件夹的Debug子文件夹中找到一个名为CDLL的DLL文件,该文件即以上的C语言源程序生成的DLL。

 

2、 使用Delphi 7编写调用该DLL的应用程序

打开Delphi 7集成开发环境,在默认生成的窗体Form1上拖放3个Edit控件Edit1、Edit2、Edit3和1个Button控件Button1,并在Object Inspector中将3个Edit控件的Text属性都清空。然后在默认生成的Unit1.pas文件的implementation后输入:

function max(x,y: Integer): Integer; stdcall external 'CDLL.DLL';

返回Form1,双击Button1控件,在生成的事件处理程序中输入:

Edit3.Text:=IntToStr(max(StrToInt(Edit1.Text), StrToInt(Edit2.Text)));

输入完毕后,保存这个Project。最后,将CDLL.dll文件copy到保存该Project的文件夹中。

 

3、 测试

在Delphi集成开发环境下,按下F9来运行刚刚编写的Project。在Edit1中输入2,Edit2中输入4,然后单击Button1,可以看到Edit3中会出现4,测试成功。


4、基础知识


4.1、回调函数


软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。其中回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础。

回调函数与普通函数的申明并无区别,但如果是不同的开发语言之间通过回调函数来传递与处理数据,则一定要注意在不同语言对回调函数的申明与实现时其函数调用约定必须保持一致。


4.2、函数调用约定


声明过程或函数时,可以指定调用约定(calling convention),尤其在以接口形式提供给其它语言工具使用时,则必须指定过程或函数的调用方式。

Delphi指定调用约定可以使用的指示字包括register、pascal、cdecl、stdcall以及safecall。C/C++调用约定有stdcall、cdecl、fastcall、thiscall、naked call等。

决定了传递给例程的参数的顺序,还影响参数从栈中的解除、参数传递时对寄存器的使用以及处理错误和异常等。缺省的调用约定是register。


下表是调用约定的简要概括:

 

指示字 ...........参数顺序 ................................................参数删除者 寄存器传递参数
register ...........从左到右 ...............................................例程 .....................是
pascal ............从左到右 ................................................例程 ....................否
cdecl ..............从右到左 .................................................调用者 ................否
stdcall ............从右到左 .................................................例程 ....................否
safecall ..........从右到左 .................................................例程 ....................否
fastcall ...........函数前两个参数通过ecx和edx传递,...例程 ................部分是
........................其他参数从右向左的顺序压栈
thiscall ...........从右到左 .................................................例程.
(非关键词)..... (this指针保存在ecx,仅用于c++)  
naked call....... 一般用于实模式驱动程序设计 ...........- .............................-


补充说明:

·cdecl调用约定又称为C调用约定,是C语言缺省的调用约定.

·register约定最多可以使用三个CPU寄存器传递参数,而其他的约定都通过栈传递所有的参数。

·safecall约定实现了异常防火墙。在Windows中,这一实现在内部处理COM错误通知。

·缺省的register约定是效率最高的,因为它通常避免了栈中新帧的创建。

·调用来自用C或C++编写的共享库的函数时,cdecl约定是很有用的;而对外部代码的调用,一般而言,推荐使用stdcall和safecall约定。

·在Windows中,操作系统API函数使用的是stdcall和safecall约定。其他操作系统通常使用cdecl约定。(注意,stdcall约定比cdecl约定具有更高的效率。)

·safecall约定必需用于声明双重接口的方法。pascal约定用于维持向后(旧版本)兼容。

 

 

posted on 2009-12-11 15:18  五维思考  阅读(399)  评论(0编辑  收藏  举报

QQ群:1. 全栈码农【346906288】2. VBA/VSTO【2660245】