delphi函数调用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi函数调用相关的知识,希望对你有一定的参考价值。

procedure SearchPath(const APath: string); //APath必须带'\'
var
SR: TSearchRec;
begin
if FindFirst(APath + '*.*', faAnyFile, SR) = 0 then
repeat
if (SR.Name <> '.') and (SR.Name <> '..') and
(SR.Attr = faDirectory) then
begin
ListBox1.Items.Add(APath + SR.Name);
SearchPath(APath + SR.Name + '\');
end;
until FindNext(SR) <> 0;
FindClose(SR);
end;

这个函数改怎么调用,我用:edit1.Text:= searchpath(edit1.Text);无效

只要你程序里面有ListBox1的话就直接searchpath(edit1.Text)就可以啦!找到适合的文件会添加到ListBox1里面 参考技术A procedure 是没有返回值的,而且看这个函数的参数,也没有赋值,你看一下FindClose()这个函数,是不是有返回值 参考技术B 没有返回值,它是在listbox1里面显示出来的.

使用扩展参数调用 Delphi 函数时出现 C++ 错误

【中文标题】使用扩展参数调用 Delphi 函数时出现 C++ 错误【英文标题】:C++ error when calling a Delphi function with Extended parameters 【发布时间】:2016-08-30 15:46:59 【问题描述】:

在一个新的 Win32 项目中,我有以下 Delphi 函数:

procedure SetValue(value1, value2 : Extended);
begin
end;

在同一个项目中,但来自 C++ 单元,我调用了这个函数:

SetValue(10, 40);

当我使用 BCC32C (CLang) 编译时检查 value1 时,我得到 1.68132090507504896E-4932,这是不正确的。

用 BCC32(经典)编译,我得到 10。

在这两种情况下,第二个参数都是 40。

Extended 值和参数堆栈加载似乎有问题。

我使用 RAD Studio 10.1 Berlin。

我该如何解决这个问题?

更新

我没有包含声明,因为 hpp 是在编译时自动创建的。无论如何,声明是:

extern DELPHI_PACKAGE void __fastcall SetValue(System::Extended value1, System::Extended value2);

复制项目:

1-在 Rad Studio 中创建 C++ 项目

2-用上面的SetValue函数添加一个Delphi单元

3-从C++单元中,用#include添加hpp头并调用SetValue

就是这样。

我需要使用扩展类型。我正在使用外部 Delphi 库,因此无法更改类型。上面的代码是对问题的简化。实际上,问题在于调用该库的函数,该函数在参数中使用了 Extended。 Extended 在 Delphi 中是本机类型,但在 C++ 中它映射为 long double、10 字节(对于 Win32)。

【问题讨论】:

从外部应用程序调用该函数时不应该将其标记为cdecl吗? 如何在 C++ 代码中声明函数? 停止使用Extended。这是个坏主意。使用DoubleRealDouble 的别名)。您只需要展示调用约定和您的 C++ 代码,我们就有机会。为什么我们不能有minimal reproducible example?我在我见过的所有问题中只问了一半。当然,消息正在传递....... @JoachimPileborg 当为 C++ 编译 Delphi 单元时,Delphi 编译器会自动生成 C++ .hpp 头文件。希望 OP 使用该标头而不是手动声明该函数。 @GuidoG 不,调用约定不需要是cdecl。并且该函数没有被外部应用程序调用。 Delphi 代码可以直接在 C++Builder 项目中使用。 【参考方案1】:

这似乎是 BCC32C 编译器中的错误。我猜它没有正确扩展来处理Extended,因为 Delphi 需要它。

如果你查看 CPU 窗口,那么 BCC32 编译器会生成:

File5.cpp.14: SetVal(10.0L, 40.0L);
00401B8F 6802400000       push $00004002
00401B94 68000000A0       push $a0000000
00401B99 6A00             push $00
00401B9B 6804400000       push $00004004
00401BA0 68000000A0       push $a0000000
00401BA5 6A00             push $00
00401BA7 E80C000000       call Unit12::SetVal(long double,long double)

这是正确的。它首先推送10,然后以Extended 格式推送40。注意每个Extended在栈上占用12个字节。

但现在看看 BCC32C 编译器的输出:

File5.cpp.14: SetVal(10.0L, 40.0L);
00401B5D 89E0             mov eax,esp
00401B5F D90554F14E00     fld dword ptr [$004ef154]
00401B65 DB38             fstp tbyte ptr [eax]
00401B67 D90558F14E00     fld dword ptr [$004ef158]
00401B6D DB780A           fstp tbyte ptr [eax+$0a]
00401B70 E81F000000       call Unit12::SetVal(long double,long double)
00401B75 83EC18           sub esp,$18

它首先读取 32 个单精度浮点数 40 并将其存储为 Extended [ESP]。到现在为止还挺好。但随后它会读取下一个 32 位单精度浮点数 10(仍然可以),然后 将其存储在 [ESP+$0A],这显然是错误的(对于 Delphi)!它应该存储在[ESP+$0C]!这就是为什么 first 值是错误的,Pascal 函数在 [ESP+$0C] 处读取,但 BCC32C 将其存储在 [ESP+$0A] 处。

所以这似乎是一个错误。举报为https://quality.embarcadero.com/browse/RSP-15737

请注意,这是 BCC32C 推送并期望此类值的正常方式。在同一模块中的 C++ 函数中,即也使用 BCC32C 编译,这很好用:

void __fastcall Bla(long double a, long double b)

    printf("%Lf %Lf\n", a, b);

但是 Delphi 期望一个 10 字节的 Extended 占用堆栈上的 12 个字节,而不是像 BCC32C 那样的 10 个字节。

很奇怪,如果要调用的函数不是 Delphi __fastcall 函数,而是普通的 C++ (cdecl) 函数,BCC32C 编译器将存储 Extendeds (long doubles ) 分别在[ESP+$0C][ESP] 中。

解决方法

正如 David Heffernan 评论的那样,您可以在记录中传递多个扩展。或者,您可以将它们作为var 参数传递。这两种情况,都不是调用SetVal(10.0, 40.0);那么简单。

【讨论】:

@David:包装确实会得到正确的对齐。 @David:很遗憾,包装不是一种选择。这个库真的很大,有数百个类,其中许多是派生类、它们之间的链接、接口等。构建一个包装器确实需要付出巨大的努力。我会考虑购买源并用另一种类型替换扩展类型。感谢您的帮助。 什么是图书馆不感兴趣? 我知道这是一个延伸,但你可以用 Delphi(可能更容易)或 C++ 的内置汇编器编写一个函数,正确对齐 Extended,然后调用你想要的函数直接调用。那么你可以称它为CallWith2Extendeds(&amp;Unit12::SetValue, 10.0L, 40.0L);。而不是SetValue(10.0L, 40.0L); 终于解决了。我可以直接使用 f->Height、f->Width 等属性,而不是调用 f->SetSize(Height, Width) 等因扩展对齐而失败的函数。谢谢你。你拯救了我的一周!。

以上是关于delphi函数调用的主要内容,如果未能解决你的问题,请参考以下文章

delphi函数调用

delphi中函数的声明和调用是啥意思?

DELPHI调用DLL时的回调函数问题

delphi 怎么动态调用dll中的过程

delphi如何调用多个参数的函数

如何从 Delphi 调用 Oracle 函数?