主页
Top.Mail.Ru Yandeks.Metrika
论坛:“主要”;
当前存档:2002.07.29;
下载:[xml.tar.bz2];

向下

调用* .dll后看不见的形式 找到类似的分支


VAleksey   (2002-07-16 13:29) [0]

我调用其中包含表单的dll程序。 表单仍然是空的,除了创建和销毁表单外,什么也没有做,但是! 调用创建并销毁窗体的dll函数后,主应用程序窗口变为不可见。
在您多次单击任务栏中的快捷方式之前,它将保持不可见。
不会发生错误。 以防万一,我什至删除了所有异常处理程序。
我做错了什么? 为什么应用程序窗口不可见? 如何解决?
PS
一点代码:))
// обьявление функции в главном модуле программы
Type
TEditAnswerGetGuess = function(AHandle:THandle; const NQ:longint):Real;
Var
EditAnswerGetGuess:TEditAnswerGetGuess;
...
// Вызов функции из длл
procedure TfmAdm.EditAnswerExecute(Sender: TObject);
Var HLib:THandle;
begin
hLib:=LoadLibrary(PChar("Answers"+FloatToStr(dm1.tbQ.FieldByName("TypeQ").Value)+".dll"));
if hLib<32 then
begin
MessageDlg("Не найдена необходимая динамическая библиотека !",mtError,[mbOk],0);
System.Exit;
end;
//try
EditAnswerGetGuess:=TEditAnswerGetGuess(GetProcAddress(hLib,"EditAnswerGetGuess"));
(Application.Handle,dm1.tbQ.FieldByName("Id_Q").AsInteger);
dm1.tbQ.Edit;
dm1.tbQ.FieldByName("Guess").Value:=EditAnswerGetGuess(Application.Handle,dm1.tbQ.FieldByName("Id_Q").AsInteger);
dm1.tbQ.Post;
//finally
FreeLibrary(hLib);
//end;
end;

...
// и напоследок код функции в длл
function EditAnswerGetGuess(AHandle:THandle; const NQ:longint):real; Export;
begin
Application.Handle:=AHandle;
fmMain1:=tfmMain1.Create(Application);
fmMain1.ShowModal;
Result:=0.5;
fmMain1.Free;
end;



Skier   (2002-07-16 13:37) [1]

> VAleksey


// обьявление функции в главном модуле программы
Type
TEditAnswerGetGuess = function(AHandle:THandle; const NQ:longint):Real; stdcall;


...
// и напоследок код функции в длл
function EditAnswerGetGuess(AHandle:THandle; const NQ:longint):real; stdcall;
begin
Application.Handle:=AHandle;
fmMain1:=tfmMain1.Create(Application);
fmMain1.ShowModal;
Result:=0.5;
fmMain1.Free;
end;



Fiend   (2002-07-16 13:38) [2]

传递给应用程序的Application应用程序的指针不是传递给函数的句柄,可能会更正确。

您可以回答DLL中应用程序的含义



Игорь Шевченко   (2002-07-16 13:41) [3]

滑雪者©(16.07.02 13:37)

为什么要使用stdcall?



Skier   (2002-07-16 13:42) [4]

>伊戈尔舍甫琴科
!!! ???



VAleksey   (2002-07-16 13:45) [5]


>滑雪者©(16.07.02 13:42)

等等

>函数EditAnswerGetGuess(AHandle:THandle; const NQ:longint):实数;
> stdcall;

编译器不会跳过。



Emfi   (2002-07-16 13:46) [6]

不太传统的方法。
尝试在调用dll函数的窗体上调用Update。



Игорь Шевченко   (2002-07-16 13:47) [7]

作者

而不是
EditAnswerGetGuess:= TEditAnswerGetGuess(GetProcAddress(hLib,“ EditAnswerGetGuess”));

尝试

@EditAnswerGetGuess:= GetProcAddress(hLib,“ EditAnswerGetGuess”);

以某种方式更规范?


滑雪者©(16.07.02 13:42)

为什么在此示例中需要stdcall?



VAleksey   (2002-07-16 13:51) [8]


> Igor Shevchenko©(16.07.02 13:47)

尝试了。 没有帮助。
但是同志


>滑雪者©

Human StdCall消除了这种废话。
滑雪者还能用一点理论来稀释答案吗? 我想知道原因。



Skier   (2002-07-16 13:55) [9]

> VAleksey
转向伊戈尔·舍甫琴科©他知道善良
网络上有关此主题的链接。



anatol   (2002-07-16 13:58) [10]

naverno potomu 4to v dll tebea funcsia obyavlena cac export avv exe ti pitashsea vizvat“ cac register(po umol4aniu)。



Игорь Шевченко   (2002-07-16 14:09) [11]

关于呼叫约定
作者:P.下面
主页:http://www.teamb.com/
0对本文的评论[写新评论]
[打印提示]

提示评分:(3):
技能:
有用:
总体而言:



调用约定影响两件事:

-如何将参数传递给函数/过程(=例程)
-通话返回时如何清理通话堆栈

Delphi例程可以使用调用约定pascal(
Delphi 1默认),注册(Delphi 2-5默认),cdecl
(C / C ++编译器使用的默认设置),stdcall(使用的默认设置
通过Windows API)。 还有第五个:safecall,
仅在接口方法的上下文中使用。 很好
有关其含义的说明,请参见问题51
(十一月99)的《 Delphi》杂志,我不再讨论
在这里。 让我们详细了解一下前四个
具有相同参数列表的几个测试功能,但
不同的调用约定。 为了清楚起见,我们使用
堆叠帧,因此每个例程都将从序言开始

推息
mov ebp,esp

下面给出的堆栈布局用于mov行。 每次测试
函数以相同的参数值调用,因此可以
使用CPU窗口堆栈窗格来研究结果堆栈
布局。

1。 Pascal呼叫约定

函数Test1(i:整数; b:布尔; d:双精度):整数;
帕斯卡;

Pascal调用约定在堆栈上传递参数,并且
在参数列表中从左到右推送它们。 每个
参数占用4字节的倍数。 生成的堆栈
布局是

ebp + i的20个值,4个字节
ebp + 16的b值,4个字节,仅低字节有效
ebp + X的08值,8个字节
ebp + 04返回地址,4个字节
ebp + 00旧的ebp值

通过调用函数从堆栈中清除参数
使用

撤回$ 10

指令($ 10 = 16是参数的总大小
堆栈)。

2。 注册通话惯例

函数Test2(i:整数; b:布尔; d:双精度):整数;
注册;

寄存器调用约定在寄存器中传递参数
eax,edx,ecx并在堆栈上并从左到右对其进行处理
在参数列表中。 有规则决定什么
进入寄存器,然后进入栈,详细说明
在对象Pascal语言指南中。 生成的堆栈布局
is

ebp + X的08值,8个字节
ebp + 04返回地址,4个字节
ebp + 00旧的ebp值

i的值以eax传递,b的值以edx传递。

通过调用函数从堆栈中清除参数
使用

撤回$ 8

指令($ 8 = 8是参数的总大小
堆栈)。

3。 cdecl调用约定

函数Test3(i:整数; b:布尔; d:双精度):整数;
CDECL;

Cdecl调用约定在堆栈上传递参数,并且
在参数列表中从右向左推动它们。 每个
参数占用4字节的倍数。 生成的堆栈
布局是

ebp + X的16值,8个字节
ebp + 12的b值,4个字节,仅低字节有效
ebp + i的08个值,4个字节
ebp + 04返回地址,4个字节
ebp + 00旧的ebp值

通过调用从堆栈中清除参数
函数,因此该函数以a结尾

撤回0

在通话说明之后,我们找到了一个

添加esp,$ 10

指令($ 10 = 16是参数的总大小
堆栈)。

4。 Stdcall调用约定

函数Test4(i:整数; b:布尔; d:双精度):整数;
STDCALL;

sdtcall调用约定在堆栈上传递参数,并且
在参数列表中从右向左推动它们。 每个
参数占用4字节的倍数。 生成的堆栈
布局是

ebp + X的16值,8个字节
ebp + 12的b值,4个字节,仅低字节有效
ebp + i的08个值,4个字节
ebp + 04返回地址,4个字节
ebp + 00旧的ebp值

通过调用函数从堆栈中清除参数
使用

撤回$ 10

指令($ 10 = 16是参数的总大小
堆栈)。

Продолжениеследует...



Игорь Шевченко   (2002-07-16 14:14) [12]

编写仅可用于Delphi的DLL时
通常会使用注册调用约定的程序,
因为它是最有效的一种。 但这确实与
DLL到Delphi,没有用其他语言编译的程序(带有
也许BC ++ Builder除外)将能够使用
DLL除非它使用汇编程序来调用函数,否则
注册调用约定(如MS VC _fastcall)为
特定于编译器。

编写应由其他程序使用的DLL时
无论使用哪种语言,您都可以使用stdcall调用约定
用于导出的例程。 可以调用Windows API的任何语言
例程将能够从这样的DLL调用例程,只要
当您远离特定于Delphi的数据类型(例如String)时,
布尔值,对象,real48。

Pascal调用约定是Win16的传统,它是默认设置
用于Win16 API,但在Win32上不再使用。

与调用约定无关的主题是名称修饰
用于DLL中导出的名称。 Delphi(至少5)没有
装饰名称,而不考虑使用的调用约定。 名字
完全按照您引用的方式出现在导出的名称表中
DLL,大小写和所有内容的exports子句。 情况是
对于Win32中的导出功能很重要!

其他编译器可能会修饰名称。 除非被告知否则
C编译器将为所有cdecl函数添加下划线前缀
并以_name @ x格式装饰stdcall函数,
其中x是参数的总大小,例如_Test3 @ 16。 C ++是
更糟糕的是,除非将函数声明为extern“ C”,否则它将
以修饰的格式导出名称,该格式编码参数大小
和类型(以特定于编译器的方式)。 对于导出的例程
使用Pascal调用约定时,名称可能全为大写,
但是如上所述,您通常不会讨论这个约定
在Win32上。

由于这些命名问题,通常适合于TDUMP
在您要连接的未知DLL上,以找出
导出函数的实际名称。 然后可以给这些
在外部语句的名称子句中,如果它们是
装饰。


演示DLL:

库DemoDLL;

使用
窗口;

函数Test1(i:整数; b:布尔值; d:双精度型):整数; 帕斯卡
开始
结果:=回合(i * Ord(b)* d);
结束;

函数Test2(i:整数; b:布尔值; d:双精度型):整数; 登记
开始
结果:=回合(i * Ord(b)* d);
结束;

函数Test3(i:整数; b:布尔值; d:双精度型):整数; cdecl;
开始
结果:=回合(i * Ord(b)* d);
结束;

函数Test4(i:整数; b:布尔值; d:双精度型):整数; stdcall;
开始
结果:=回合(i * Ord(b)* d);
结束;

出口
Test1索引1,
Test2索引2,
Test3索引3,
Test4索引4;

开始
结束。


//来自测试项目的示例调用:

履行

{$ R * .DFM}

函数Test1(i:整数; b:布尔值; d:双精度型):整数;
帕斯卡 外部“ DEMODLL.DLL”索引1;

函数Test2(i:整数; b:布尔值; d:双精度型):整数;
登记 外部“ DEMODLL.DLL”索引2;

函数Test3(i:整数; b:布尔值; d:双精度型):整数;
cdecl; 外部“ DEMODLL.DLL”索引3;

函数Test4(i:整数; b:布尔值; d:双精度型):整数;
stdcall; 外部“ DEMODLL.DLL”索引4;

过程TForm1.Button1Click(Sender:TObject);
VAR
我:整数;
开始
i:= Test1(16,True,1.0);
i:= Test2(16,True,1.0);
i:= Test3(16,True,1.0);
i:= Test4(16,True,1.0);
结束;



在行上设置断点,并使用
CPU窗口打开以查看堆栈布局。




VAleksey   (2002-07-16 14:19) [13]

喔...喔...喔...喔
更好的邮件!
> Igor Shevchenko©(16.07.02 14:09)




VAleksey   (2002-07-17 13:18) [14]

Mlyn,我的电子邮件又来了,是的,好的,表格消失了!



Страницы: 1 整个分支

论坛:“主要”;
当前存档:2002.07.29;
下载:[xml.tar.bz2];

楼上





内存:0.61 MB
时间:0.028 c
1-95363
疯子
2002-07-14 16:05
2002.07.29
Исключения


3-95214
ppcat
2002-07-06 09:04
2002.07.29
ADO,MS SQL 7.0和更新的视图


3-95262
最大
2002-07-09 14:31
2002.07.29
列表中的棘手选择


14-95510
Svge
2002-07-02 12:09
2002.07.29
用户的ISA流量限制


1-95358
皮肤
2002-07-17 22:52
2002.07.29
系统托盘





南非荷兰语 阿尔巴尼亚人 阿拉伯语 亚美尼亚 阿塞拜疆 巴斯克 白俄罗斯 保加利亚语 加泰罗尼亚 简体中文 中国(繁体) 克罗地亚 捷克 丹麦语 荷兰人 英语 爱沙尼亚语 菲律宾人 芬兰 法语
加利亚西语 格鲁吉亚语 德语 希腊语 海地克里奥尔语 希伯来语 印地语 匈牙利 北日耳曼语 印度尼西亚人 爱尔兰语 意大利语 日本 韩语 拉脱维亚 立陶宛 马其顿 马来语 马耳他语 挪威语
波斯语 波兰语 葡萄牙语 罗马尼亚 俄语 塞尔维亚 斯洛伐克 斯洛文尼亚 西班牙语 斯瓦希里 瑞典语 泰国人 土耳其 乌克兰 乌尔都语 越南人 威尔士语 意第绪语 孟加拉 波斯尼亚
宿务 世界语 古吉拉特语 豪萨语 苗族 伊博 爪哇 卡纳达语 高棉 老挝 拉丁语 毛利 马拉 蒙古人 尼泊尔 旁遮普 索马里 淡米尔文 泰卢固语 约鲁巴语
祖鲁
英文 Французский Немецкий Итальянский Португальский 俄文 Испанский