类型:转载 责任编辑:asp.net 日期:2007/05/23
热门软件下载:
我在使用DCP控件中的MD5控件编写一个DLL文件,代码如下:
Function MD5(Str:String):String;
var
dcpMD5: TDCP_md5;
Len,i:integer;
HashDigest:array[0..31]of byte;
MiWen:String;
begin
dcpMD5:=TDCP_md5.Create(nil);
try
dcpMD5.Init;
dcpMD5.UpdateStr(Str);
dcpMD5.Final(HashDigest);
Len:=dcpMD5.HashSize;
MiWen:=;
For i:=0 to ((Len div 8)-1) do
MiWen:=MiWen+IntToHex(HashDigest[i],2);
Result:=MiWen;
Finally
dcpMD5.Free;
end;
end;
exports
MD5;
然后用程序分别使用动态(显式)和静态(隐式)调用,但都在调用时出错了。
用动态调用直接在DLL内部出错,出错内容如下:
Access violation at address 00373F14 in module MD5DLL.dll. Write of address 00000030.
用静态调用就在程序调用DLL函数后,并正常返回了数据后才出错,错误如下:
Invalid pointer operation.
但如果把DLL中的返回result:=MiWen;改为ShowMessage(MiWen)就能正常调用了(我加了Dialogs)
我真的不明白错在那里了,DLL需要用到函数返回时需要注意些什么呢?我第1次写DLL,希望各位教育一下,谢谢!!!
网友回答:
1. 所需动态连结的 DLL 须置放在与执行档同一目录或Windows System 目录
2. 确认 DLL export 出来的函式的原型, 以目前的情况而言, 通常只拿得到 C 语言的函数原型, 这时要注意 C 与 object Pascal 相对应的型别, 如果需要, 在 interface 一节定义所需的资料类别
3. 在 implementation 节中宣告欲使用的函式, 语法大致如下:
procedure ProcName(Argu...); far; external DLL档名;
index n;
function FuncName(Argr...): DataType; far;
external DLL档名; index n;
宣告时, index n 如果不写, 便是叁考资料中所谓 import by name 的方式, 此时, 由於需要从 DLL 的 name table 中找出这个函式, 因此, 连结执行速度比 import by ordinal稍慢一些
此外, 还有一种 by new name, 由於我没用过, 您可以查一叁考资料, 大意是可以 import 後改用另一个程式命名呼叫这个函式
4. 然後, 呼叫与使用就与一般的Delphi 没有两样
5. 上述是直接写到呼叫DLL函式的程式单元中, 此外, 也可以将DLL的呼叫宣告集中到一个程式单元(Import unit), Delphi 内附的 WinTypes, WinProcs 是一个例子, 您可以叁考一下,同时观察一下 C 与 Pascal 互相对应的资料型态
6. 除了上述的 static import 的方式, 另外有一种 dynamic import 的写法, 先宣告一个程序类型(procedural-type),程式执行时, 以 LoadLibrary() API Load 进来後, 再以 GetProcAddress() API 取得函式的位址的方式来连结呼叫, 在 Object Pascal Language Guide P.132-133 有一个例子, 您可以叁考看看
这个和调用方式无关,每个DLL工程前面都有的一段话,仔细看了就没有这个问题了
{ Important note about DLL memory management: ShareMem must be the
first unit in your librarys USES clause AND your projects (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
即使用String就要uses ShareMem,否则就不要用String做参数,而用PChar代替