我有几年前用C++中的旧Win32 API编程的经验,最近我参与了Delphi的开发.我马上就认出了很多从Windows API函数(如CreateThread
,CreateWindowEx
等,等).
我发现Embarcadero的文档不完整(至少可以说),通常可以参考Microsoft网站获取文档.在哪里,我可以补充一下,所有的功能都是用C语言定义的,这使得那里的非C人很难(但对我来说更容易).
我想知道的是 - 鉴于Delphi函数签名与Microsoft提供的C函数签名相同 - 调用Delphi Windows API函数会立即调用Windows API函数,还是调用相同的Delphi函数然后调用它调用Windows API函数并返回结果,前者意味着与相应的C代码相比没有可区别的性能差异,而后者意味着性能损失?
Ken*_*ite 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';
Run Code Online (Sandbox Code Playgroud)
所以你的具体问题的答案是否定的.没有性能损失.在Delphi中调用WinAPI函数不会导致性能损失.
调用Delphi Windows API函数是否立即调用Windows API函数?
不是没有.
为了争论,让我们考虑一下CloseHandle
.这在Windows
单元中声明并使用实现external
.当你调用它,你实际上调用名为功能CloseHandle
的Windows
单元.所以在伪汇编程序中它看起来像这样:
.... prepare parameters
CALL Windows.CloseHandle
Run Code Online (Sandbox Code Playgroud)
然后,Windows.CloseHandle
实现如下:
JMP kernel32.CloseHandle
Run Code Online (Sandbox Code Playgroud)
因此,与直接调用相比,调用thunk函数,然后跳转到Win32 DLL.这被称为蹦床.
它可以以不同的方式实施.编译器可以发出代码直接调用Win32 DLL.一些编译器会这样做.例如,MSVC发出的此调用的等效asm将是:
CALL DWORD PTR [__imp__CloseHandle@4]
Run Code Online (Sandbox Code Playgroud)
这里,__imp__CloseHandle@4
是内存中包含CloseHandle
Windows DLL中地址的位置的地址.装载机写的实际地址CloseHandle
为__imp__CloseHandle@4
在加载时间.
哪个更有效率?没有剖析,不可能肯定地说.但我相信,在极少数情况下,任何差异都会很大.
当然,也可以生成直接调用而没有间接调用的代码.这将涉及加载器补丁每次调用该函数.这可能是一个坏主意,但是因为它会导致大量的加载时间修复,这将是启动时的性能问题.也就是说,它与需要在加载时重新定位的DLL几乎相同.无论如何,我知道没有采用这一政策的工具链.
也许你关心的是这些函数是否是真正的Win32函数.或者它们周围是否有一层改变了意义.这些是真正的Win32功能.没有Delphi文档,因为它们是Win32函数.MSDN上的Win32文档是文档的权威来源.
正如许多人所说,Win32函数被调用而没有中间层.因此,在这些意义上直接调用它们将您的参数未经修改地传递给API函数.但是呼叫机制是间接的,因为它使用蹦床.语义上没有区别.
归档时间: |
|
查看次数: |
689 次 |
最近记录: |