通过Delphi访问Windows API会有性能损失吗?

问题描述 投票:8回答:2

我有几年前用C ++中的旧Win32 API编程的经验,最近我参与了Delphi的开发。我立即认识到Windows API中的许多功能(例如,CreateThreadCreateWindowEx等)。

我发现Embarcadero的文档不完整(至少可以说),通常可以参考Microsoft网站获取文档。在哪里,我可以补充一下,所有的功能都是用C语言定义的,这使得那里的非C人很难(但对我来说更容易)。

我想知道的是 - 鉴于Delphi函数签名与Microsoft提供的C函数签名相同 - 调用Delphi Windows API函数会立即调用Windows API函数,还是调用相同的Delphi函数然后调用它调用Windows API函数并返回结果,前者意味着与相应的C代码相比没有可区别的性能差异,而后者意味着性能损失?

c++ delphi winapi
2个回答
20
投票

阅读来源。对CreateWindowEx单元的调用在Windows.pas单元中定义为直接调用CreateWindowExW中的User32.DLL函数(来自XE5的源代码 - 类似的定义可在所有版本的Delphi中找到支持的OS版本):

function CreateWindowEx(dwExStyle: DWORD; lpClassName: LPCWSTR;
  lpWindowName: LPCWSTR; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
  hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
  stdcall; external user32 name 'CreateWindowExW';

所以你的具体问题的答案是否定的。没有性能损失。在Delphi中调用WinAPI函数不会导致性能损失。


9
投票

调用Delphi Windows API函数是否立即调用Windows API函数?

不是没有。

为了论证,我们考虑一下对CloseHandle的调用。这是在Windows单位宣布并使用external实施的。当你调用它时,你确实在CloseHandle单元中调用了一个名为Windows的函数。所以在伪汇编程序中它看起来像这样:

.... prepare parameters
CALL     Windows.CloseHandle

然后,Windows.CloseHandle实现如下:

JMP      kernel32.CloseHandle

因此,与直接调用相比,调用thunk函数,然后跳转到Win32 DLL。这被称为蹦床。

它可以以不同的方式实施。编译器可以发出代码直接调用Win32 DLL。一些编译器会这样做。例如,MSVC发出的此调用的等效asm将是:

CALL     DWORD PTR [__imp__CloseHandle@4]

这里,__imp__CloseHandle@4是内存中某个位置的地址,其中包含Windows DLL中CloseHandle的地址。加载程序在加载时将CloseHandle的实际地址写入__imp__CloseHandle@4

哪个更有效率?没有剖析,不可能肯定地说。但我相信,在极少数情况下,任何差异都会很大。

当然,也可以生成直接调用而没有间接调用的代码。这将涉及加载器补丁每次调用该函数。这可能是一个坏主意,但是因为它会导致大量的加载时间修复,这将是启动时的性能问题。也就是说,它与需要在加载时重新定位的DLL几乎相同。无论如何,我知道没有采用这一政策的工具链。

也许你关心的是这些函数是否是真正的Win32函数。或者它们周围是否有一层改变了意义。这些是真正的Win32功能。没有Delphi文档,因为它们是Win32函数。 MSDN上的Win32文档是文档的权威来源。

正如许多人所说,Win32函数被调用而没有中间层。因此,在这些意义上直接调用它们将您的参数未经修改地传递给API函数。但是呼叫机制是间接的,因为它使用蹦床。语义上没有区别。

© www.soinside.com 2019 - 2024. All rights reserved.