奇怪、奇怪、真奇怪!(0分)

J

Jams

Unregistered / Unconfirmed
GUEST, unregistred user!
对于Dll最好的例子就是字符串反转了,即ReverseStr,这在大多数的书常
作为典型的事例进行介绍。本人也曾按书中的方法实现过,并将处理过秤记录
于书上(因为书中并无该例程的调用),运行环境为D3.
可是,近几日本人又需要此了,按书中的例程输入,确出了问题,该想到的都
想到了,并卸掉D4,装D3,问题依然如此。重装D4,无任何好转,部分实例:

Uses
...

Procedure ReverseStr(toReverseStr: PChar); Export; stdcall; (1)
Begin
myDll(toReverseStr); (2)
End;

Exports;
ReverseStr;

Begin
End.

若按(1)式写,则在运行时,跟踪至(2)时,ToReverseStr的值为',**'杂乱无章
的字串,长度为3;
若将(1)中的Stdcall去掉,则(2)中的ToReverseStr则为调用程序传过来的
字串。
感到奇怪的是,原先使用该过程时一点毛病没有,咋今天又出猫儿眼了?书上
说stdcall可为以后各软弱的调用设置的,最好带着它,不知为何有了stdcall
就出问题了?!
 
如果用了stdcall的话, import的时候也要指出是stdcall的
我还没是过,不过应该是因为双方的发生了误解
 
主调用仅有
Type
TmyDll=Procedure(varStr: String);
一句,在何处使用Import的stdcall呢?显然Type后不能加stdcall!
再有,原先运行时好象没那么多毛病(一字不撂),是否是Win98-->win95就不认了,
还是将WinFast显卡换成S3 64V+的事,如何解释得清楚?
 
Type
TmyDll=Procedure(varStr: String);stdcall;
 
Type后好象不能加stdcall吧?但stdcall前我用的是';(分号)',难道与此有关吗?
 
可以用, 而且是分号
 
还有一个错误:
Type
TmyDll=Procedure(varStr: PChar);stdcall;
^^^^^^^ 你的问题大概就在这了
 
no!no!
Type一句就应是String类型,此句的意思是进行函数的强制类型转换。换过PChar
类型,也不行!除非将Dll中(1)的stdcall去掉才能得到正常结果。不知stdcall
与dll又“闹”什么别扭了?
 
type声明的参数类型与调用方式(stdcall, register,...)必须和dll输出函数或过程一致.
type中不存在什么强制转换.
强制转换只能在调用时用
如:
type
TMyDll = procedure(str: Pchar); stdcall;

implimentation

procedure calldll(str: string);
var
mydll: TMydll;
dllHandle: Integer;
begin
dllhandle := LoadLibrary('Mydll.dll');
if dllhandle > 0 then
begin
@mydll := GetProcAddress(dllhandle, 'ReverseStr');
mydll(pchar(str));
freelibrary(dllhandle);
end;
end;
 
还有一个怪事!若不去掉(1)中的Stdcall,在主调用程序里执行

mydll.FreeLibary(hLib); //释放Dll所占的内存

一句时,D4/D3就出现错误,并弹出CPU调试窗口,而后死机。
而将(1)中的stdcall去掉,则无任何问题。不知为甚?
 
你调用时声明不对, 调用时如果不加stdcall用的是register调用, 通过寄存器传递参数,
stdcall是通过堆栈传递参数. 调用时压栈大小不一样. dll退出时恢复堆栈是根据你在dll中定义的调用方法和参数数量来决定的, 如果调用者根据register方式压栈, 返回按stdcall方式恢
复堆栈当然会出错(退栈太多, 返回地址不对了).反过来也一样, 只有双方调用方式一致dll返回
时才能正确退栈并取得正确返回地址.
 
to Another_eYes
我说的每一句,程序的每个字符都是书上说的,本人无任何篡改,但你的用法有点
意思,明日一试!
 
忠告:
千万别看书(中文翻译书).
 
to Another_eYes
1,你上面的分析很有道理,但最初我就是按此做的,一点错误(毛病)都没有,而且
也得到了反转后的字符串,对此,本人记忆犹新,否则为何觉得奇怪呢!
2,我说的书是新近发行的,“用Delphi进行动画设计”中关于使用Dll的原理与应用
一章,其事例也是上面的。由于本人对此特感兴趣,所以原先的运作过程没有忘,
故才有现今的感慨。你若有空儿,可到书店去查阅一下该书,便知!
 
没见过那书,不过书学错也常有的说,既然以前你做对了,书上的错了又如何呢?
 
原来一知半解, 囫囵吞枣. 现在想具体了解了, 又遇到书上错了.

呵呵, 了解水平了.
 
to 诸位:
那本书我今天拿来啦,为"Delphi编程现学现用--动画制作与技巧”,电子科技
出版社出版。
书上的Dll实例没错,就是有错我也都改过来啦!现在贴在此的问题是无任何错误
可言的,因为去了Dll中(1)式的stdcall,结果都正确!关键还是这个stdcall
有何冲突(内存、主板、OS等)
to eyes:
你的例子我看了,与我的别无长物,但还是书上的较为精炼、合理。有空看一下
此书就知道了。

继续讨论
 
重获有先级
 
>书上的Dll实例没错,就是有错我也都改过来啦!
既然已经出错了何言没错?

>Procedure ReverseStr(toReverseStr: PChar); Export; stdcall; (1) :DLL
> TmyDll=Procedure(varStr: String); :CALL
如果书上真是这样写的,那书肯定写错了.
请参考DELPHI自己的头文件,调用DLL的方
法有几种,但没有见过这样用的.如果这样
侥幸用成功了,那也是偶尔的事.

这是DELPHI中Winsock的一个函数:
...
type
...
function inet_addr(cp: PChar): u_long; stdcall; {PInAddr;}{ TInAddr }
...
const
winsocket = 'wsock32.dll';
...
implementation
...
function inet_addr; external winsocket name 'inet_addr';
...

这是一种分开的写法,还有合起来的写法.这里有两个要点:
1.string和PChar肯定是不同的.如果混用PCHAR和STRING,可能偶尔能成功.
2.stdcall和fastcall是不同的,DELPHI缺省用fastcall,所以如果用
stdcall,必须都用.不能说实现用stdcall,调用用fastcall.

看到上面那种写法,就不应该认为是正确的.即使有几十个人宣称他们用
那种方法成功了,我也决不会用那种写法.
 
顶部